6
votes

Savoir si une valeur peut être appelée

Notez que cette question concerne Pure Lua. Je n'ai accès à aucun module ni au côté C. De plus, je ne peux pas utiliser l'IO, le système d'exploitation ou la bibliothèque de débogage.

Ce que j'essaie de faire est une fonction qui reçoit, comme paramètres:

  • un nombre qui est un nombre de seconde
  • une valeur appelable

    par 'une valeur appelable', je veux dire une valeur qui peut être appelée. Cela peut être:

    • une fonction
    • une table avec une métables qui permet d'appeler (via un __ appel métaméthod)

      Voici un exemple de table appelable: xxx

      voici la fonction: xxx

      mais J'ai un problème. Je souhaite que la fonction jette une erreur si le paramètre 'Func' n'est pas appelable.

      Je peux vérifier s'il s'agit d'une fonction. Mais que se passe-t-il s'il s'agit d'une table avec une métabilité qui permet d'appeler? Si la métatique de la table n'est pas protégée par un champ __ métaminé , je peux vérifier la métabilité pour savoir s'il est appelable, mais, sinon, comment je le ferais? < P> Notez que j'ai également pensé à essayer d'appeler le paramètre «Func» avec PCALL , pour vérifier s'il est appelable, mais pour le faire, je dois l'appeler prématurément.

      Fondamentalement, voici le problème: J'ai besoin de savoir si une fonction / table est appelable, mais sans essayer de l'appeler.

lua

0 commentaires

3 Réponses :


5
votes

En général, si la métabilité ne veut pas que vous puissiez l'obtenir (en définissant __ métables code> pour être quelque chose de spécial), alors vous n'allez pas l'obtenir. Pas de Lua.

Cependant, si vous voulez tricher, vous pouvez toujours utiliser débog.getmetable code>, qui retournera la métabilité associée à cet objet. P>


Vous n'avez pas à appeler prématurément quoi que ce soit avec PCALL code>. Observez: P>

pcall(function(...) return PossibleFunction(...) end, <insert arguments here>)


10 commentaires

J'ai oublié de mentionner que je n'ai pas accès à la bibliothèque de débogage non plus, j'ai édité mon message original pour la spécifier.


Eh bien, cela signifie qu'il n'ya aucun moyen de savoir est une valeur est appelable sans essayer de l'appeler, sauf en utilisant la bibliothèque de débogage? Si oui, c'est un peu ennuyeux, puisque je suis un nist perfection et que je veux pouvoir appeler toute valeur appelable, tout en étant capable de lancer une erreur si la valeur n'est pas appelable.


Eh bien, j'ai besoin de savoir si la valeur est appelable. Si c'est le cas, j'attends un certain nombre de secondes de secondes, puis l'appelez. Sinon, je jette une erreur. Si j'essaie d'appeler la valeur, il fonctionnera et fera des choses qui n'étaient pas censées être faites encore.


@Mark: Eh bien, non, il n'y a rien que vous puissiez faire. Vous pouvez tester des échecs évidents (pas une fonction ou des données utilisateur), mais vous allez finalement avoir à espérer le meilleur. Utilisez simplement le PCALT sur le site final de l'appel et échouez alors.


J'ai pensé à utiliser PCALL sur le site final de l'appel, mais je n'aime pas l'idée de l'erreur en prenant trop de temps pour apparaître. Mais, je pense que c'est ce que je vais faire: je vais d'abord vérifier s'il s'agit d'une fonction ou d'une table. Si ce n'est pas le cas, ça fait des erreurs. Sinon, il attend le nombre de secondes spécifiées et tente ensuite d'appeler la fonction. Si cela ne peut pas être appelé, jette une erreur. Sinon, rien ne fait rien.


Eh bien, je suppose qu'il n'y a aucun moyen d'obtenir exactement ce que je veux, je vais rester avec ce que je peux faire. Merci pour l'aide.


J'aime cette question tell-ne-pose pas. Je faisais une fonction "Iscallable", mais je pourrais copier ce style. La fonction anonyme est-elle obligatoire? Vous ne pouvez pas simplement faire PCALL (Postimunction, paramètres) ?


Notez que userData est également appelable, de la même manière une table. Le modèle général de Lua doit juste tenter d'appeler la valeur. S'il est appelable, cela fonctionne. Sinon, la tentative d'appel va elle-même lancer une erreur. La seule raison d'interposer un PCALL ici est de modifier l'erreur lancée.


@Rberteig: La raison du PCALL est de sorte que le fil actuel de l'exécution de Lua ne s'arrête pas (sauf si vous le souhaitez). Vous ne voulez pas nécessairement que certaines choses errentent à l'utilisateur. Parfois, vous voulez vraiment que Lua n'arrête pas. Mais parfois tu ne le fais pas. Parfois, vous voulez pouvoir contourner l'erreur.


@Nicol the OP a dit que le plan devait "lancer une erreur si le paramètre" FUNC "n'est pas appelable", que j'ai interprété pour signifier appel erreur () . Cela suppose que l'appelant a déjà utilisé PCALT déjà ou est préparé autrement pour gérer ce cas gracieusement. Si on souhaite empêcher une erreur de sortir de la fonction de délai de l'OP , il doit utiliser un PCALL pour l'attraper et gérer la conséquence de manière appropriée. Mais c'est un détail de mise en œuvre par rapport à la question plus grande des tests d'appelabilité. Là, la réponse est simplement appelée (ou PCALL ).



1
votes

Cette tentative de raffinage de la réponse de Nicol a toujours le problème qu'il doit appeler la table, mais il indique si une table fournie était en fait appelable ou non. Même si la table était appelable, pcall () code> retournera faux code> s'il y a une erreur causée lors de l'exécution du __ appel () code> méthamisthod.

local result = {pcall(PossibleFunction, ...)}

if not result[1] then
    if result[2]:match"^attempt to call" then
        error("The provided value is not callable.")
    else
        -- Table was callable but failed. Just hand on the error.
        error(result[2])
    end
end

-- Do something with the results:
for i = 2, #result do
    print(result[i])
end


0 commentaires

1
votes
> = iscallable(function() end)
true
> = iscallable({})
false
> = iscallable()
false
> = iscallable(nil)
false
> x = {}
> setmetatable(x, {__call=function() end})
> = iscallable(x)
true

0 commentaires