9
votes

Passage et sauvegarde de la fonction anonyme à Matlab

Je voudrais une fonction (par exemple, une fonction d'ajustement) pour renvoyer une fonction anonyme (généralement stockée dans un struct ) que je peux enregistrer et utiliser ultérieurement. Cependant, passer @func tend à transmettre un pointeur de fonction plutôt que la fonction elle-même. Est un inline fonctionne le seul moyen de faire cela? Je voudrais éviter en ligne car il est extrêmement lent.

Si cette question n'est pas claire, voici un échantillon de code problématique: j'écris un testfunc.m Fichier dans certains chemin xxx

i alors stocke la fonction dans un struct . (Je sais que cela devrait vraiment être un objet!) xxx

si je déplace ensuite myfile.mat ou testfunc.m et charger myfile.mat , je ne peux pas charger l'ancienne structure. Au lieu de cela, je reçois l'erreur: xxx

Je sais qu'il ya un problème car, si je vérifie fonctions xxx < / Pré>

Y a-t-il un moyen de supprimer les informations d'espace de travail de fichier? Sont inline fonctionne la seule solution?


3 commentaires

Je pense que je comprends le point un peu mieux - merci pour toute la discussion! Pour le moment, j'utilise des fonctions intégrées, même si elles sont lentes:% testfunc.m Fonction MyFuncC = TestFunc () myfunc = Inline ('x. ^ 2'); finir


AH - Si vous avez juste besoin de fonctions qui peuvent être exprimées en tant qu'inlines, je pense que vous pouvez utiliser des fonctions anonymes "sanité" à partir d'un espace de travail commun et propre comme remplacement d'une liste déroulante pour en ligne () et évitez le ralentir; Voir ma réponse mise à jour.


De plus, vous pouvez utiliser addpath () pour gérer votre chemin si vous n'êtes pas déjà. Cela vous permet de garder votre code source sur le chemin MATLAB, quel que soit votre répertoire actuel.


4 Réponses :


2
votes

Ce n'est pas possible, car il viole le concept de fermeture . Imaginez que vous définissez votre fonction anonyme de la manière suivante:

 handleClass.DX = 100;
 fOut(4)


9 commentaires

Pas tout à fait vrai: les fonctions anonymes ne sont pas des fermetures; Ils capturent la valeur dans les variables au moment de la construction de la fonction anonyme. Il est seulement nommé des fonctions nichées qui sont en réalité des fermetures et capturent des références en direct aux variables dans l'espace de travail enfermé.


@Andrewjanke, tu as raison bien sûr. Mais y aurait pu être une poignée et vous ne pouvez pas capturer sa valeur.


@Andrewjanke, veuillez consulter la réponse mise à jour. J'ai écrit une explication plus longue. J'aimerais entendre votre opinion. Merci!


Ah raison. Et c'est pire - y aurait pu être une poignée, mais la sortie arg f est certainement une poignée.


Bien. Ça a du sens. Mais cela ne signifie pas que vous pourriez jamais sauvegarder une poignée de fonction anonyme avec ses espaces de travail - vous ne pouviez tout simplement pas si elles contiennent une poignée. Le même argument s'applique aux cellules: En général, une matrice de cellule pourrait contenir une poignée, mais nous pouvons toujours économiser des cellules aussi longtemps que la valeur de cellule particulière que nous économisons. Je pense que la même chose s'appliquerait aux poignées de fonction anonymes avec des espaces de travail capturés; C'est le cas malheureux que l'argument de sortie nommé signifie que l'espace de travail sera contenir toujours une poignée à la fonction anonyme.


@Andrewjanke, tu as raison bien sûr. C'est pourquoi je pense que vous devriez définir votre réponse, c'est assez légitime IMHO :)


Et Matlab vous permettra d'enregistrer des poignées comme celle FOO et reconstruire leur identité lorsque vous les chargez dans. Comme la sérialisation de Java. Je ne pense pas que le problème est de pouvoir capturer les valeurs d'espace de travail en soi, c'est que Matlab souhaite que le fichier source soit présent, même si (je ne pense pas), il est en fait nécessaire de reconstruire le comportement de la fonction anonyme.


Oh merci. :) Eh bien, il est toujours éclaté - car il fonctionne, vous devez entrer et assommer les poignées de la fucnation anonyme des espaces de travail. Que vous pouvez faire, mais à ce moment-là, c'est un hack assez malade Je ne suis pas sûr que je suis à l'aise en l'approuvant en public ...


Laissez-nous Continuer cette discussion en chat



8
votes

Le cas simple

Si les fonctions que vous souhaitez être anonymes sont limitées à être définies uniquement en termes de paramètres d'entrée (comme en ligne Les fonctions sont) et vous pouvez vous engager à conserver un Fonction sur votre chemin, alors vous pouvez faire des fonctions anonymes "désinfectées". xxx

Donc, dans votre code, où vous voulez faire une fonction anonyme, faites ceci. xxx

tant que Sanitized_anon_fcn.m reste sur votre chemin, vous pouvez supprimer TestFunc2 et la fonction enregistrée continuera à fonctionner. Aucun traitement spécial nécessaire sur la sauvegarde ou la charge. sanitized_anon_fcn fonctionne essentiellement comme en ligne mais produit des fonctions aussi rapides que les fonctions anonymes (car elles sont des fonctions anonymes). La différence de vitesse est d'environ 10 fois dans R2011B sur mon ordinateur.

L'affaire Général

Dans l'affaire Général, où les fonctions pourraient en réalité utiliser des variables de leur espace de travail, les choses deviennent plus difficiles. < / P>

CAVEAT : Ceci est un peu malade, et je n'approuve pas son utilisation dans le code de production. Mais comme exemple de la façon dont la langue fonctionne, je ne peux pas résister à la poster.

Je pense que vous êtes déjà de 90%. Mais vous devez conserver les informations de l'espace de travail au lieu de le décaper, car elle peut contribuer au fonctionnement de la fonction. Au lieu d'enregistrer la fonction de fonction anonyme, saisissez la sortie de ces fonctions () appelez que vous faites et enregistrez que . xxx

puis le charger. Vous obtiendrez toujours le même avertissement, mais l'avertissement s'applique maintenant uniquement aux poignées de fonction capturées dans l'espace de travail de votre fonction anonyme de niveau supérieur. Si votre fonction ne les réfonge pas réellement (et que cela ne devrait pas), vous pouvez ignorer l'avertissement et cela fonctionnera. xxx

puis transmettez-le à quelque chose comme ça Fonction qui apportera votre fonction anonyme de la fonction morte dans un nouvel espace de travail avec les mêmes valeurs de l'espace de travail, plus ou moins. xxx

dans notre exemple d'exemple: < pré> xxx

MAINTENANT, toutes les fonctions anonymes chargées prétendent être à partir de ce nouveau fichier, mais cela ne devrait pas avoir d'importance, car il ne s'agit que de l'état d'instantané de l'espace de travail, pas de variables cloudées, que est utilisé par les fonctions anonymes. Et dans le cas où il y avait des poignées de fonction anonymes dans l'espace de travail qui ont été utilisées par le calcul, vous obtiendrez une erreur appropriée en disant "la poignée de fonction non définie".

C'est un piratage, mais peut-être que vous pourrait prendre cela et l'étendre à quelque chose de raisonnablement robuste.


1 commentaires

Désolé je ne pouvais pas discuter avec toi hier. J'étais un peu somnolent :) Quoi qu'il en soit, votre piratage a l'air bien, tant que vous comprenez les limitations.



1
votes

J'ai déjà rencontré ce problème. str2func code> est presque identique à l'opérateur de la poignée ( @ code>) - il ne crée pas l'association de fichiers, ni ne conserve les variables d'espace de travail. Dans votre cas:

myfunc = str2func('@(x) x.^2');


0 commentaires

0
votes

Élargir sur la suggestion par @Arthurward:

Pour sauvegarder des fonctions en ligne simples à partir de votre environnement de code, essayez p> xxx pré>

func2tr () active votre fonction dans une chaîne littérale , et str2func () le retourne dans une poignée que Matlab traite des dépendances exemptes de dépendances. P>

Vous pouvez le ranger en faisant nommer quelque chose comme P>

export_function = @(h) str2func(func2str( h ));


0 commentaires