tags:

views:

109

answers:

4

Isn't it weird that

ask-params: funct[config-file [file!] default-class-name default-fields][
  probe  value? 'class-name
  input
  either (value? 'class-name) [
    probe class-name
  ][
  ]
]

ret-block: ask-params %askcodegeneration.com/csharp/simple-class/simple-class.params.txt "Person" "First Name, Last Name"

would return false for value? 'class-name

but that

ask-params: funct[config-file [file!] default-class-name default-fields][
  probe  value? 'class-name
  input
  either (value? 'class-name) [
    probe class-name
  ][
    class-name: default-class-name
  ]
]

ret-block: ask-params %askcodegeneration.com/csharp/simple-class/simple-class.params.txt "Person" "First Name, Last Name"

would return true for value? 'class-name

In second case class-name: default-class-name isn't even executed yet so class-name shouldn't exist in memory and so value? 'class-name should not return true.

+2  A: 

You are using 'funct. This scans the body of the function and creates the local variables for you so that value? 'class-name becomes true.

If you used 'func instead, then both would return false.

Graham Chiu
Ah that's it. But this should be considered a bug because that is not the expected behavior of a function. funct shouldn't behave differently from func except for the variables being turned local.So I have to return to func and declare all my variables local just because funct not behaves like a true function ? That defeats the purpose of having created funct.
Rebol Tutorial
funct is syntactic sugar for func /local.It scans the body of the function for you looking for set-words, and creates them as /local. If you declare them with /local, the effect is the same.
Graham Chiu
I don't think it should be considered a bug, because it cannot work any other way. Remember that in REBOL, the only context that can be expanded dynamically is the global one. In your case, the behavior is exactly as expected: a context is created and words are bound to it.
Gregory Higley
It's a bug because it doesn't behave as a user would expect or it should documented explicitely and says: it's impossible to use value? with funct.
Rebol Tutorial
I mean doc implicitely says funct behaves exactly like func /local. but that is not the case. And I'm not interested in using funct if value? and maybe other functions don't work exactly as with func /local.
Rebol Tutorial
/local is daunting because you have to not forget to add local vars but I prefer that rather than realize I need to use it finally just because I need to use value? function.
Rebol Tutorial
So funct sucks I'll never use it :)
Rebol Tutorial
`funct` behaves exactly like `func /local`. You can read the source to confirm this. Or you can show an example where they behave differently. So far you seem to have done neither.
earl
+1  A: 

Here I show you two examples not using FUNCT, but otherwise equivalent to your code:

ask-params: func [config-file [file!] default-class-name default-fields] [
  probe  value? 'class-name
  input
  either (value? 'class-name) [
    probe class-name
  ][
  ]
]
ask-params: func [
  config-file [file!] default-class-name default-fields /local class-name
] [
  probe  value? 'class-name
  input
  either (value? 'class-name) [
    probe class-name
  ][
  ]
]

While the value? function in the first example yields #[true], in the second example it yields #[false]. That is because the "refinement arguments" following an "unused refinement" (a refinement that is not used in the actual call) are initialized to #[none!] together with the refinement variable. This applies to the /local variables as well, since the /local refinement does not differ from other function refinements (except for the fact, that it is a convention to use it to define local variables).

Since the funct function uses the /local method to implement local variables "under the hood", the above description applies to all functions it generates as well.

Ladislav
Thanks ladislav I know about /local but it's so daunting to add to /local each time you add an other variable so that you forget to do it. Now I finally prefer func and /local if funct is not able to behave exactly like func /local.
Rebol Tutorial
+1  A: 

Correction to the note contained in the previous answer - actually the expected results of the value? function call should be the other way around, which means, that the function call in the first example is expected to yield #[false], while the function call in the second example is expected to yield #[true].

Since it looks, that there is a demand to not use FUNC/LOCAL call in the answer, here is another variant using FUNCT to compare:

ask-params: funct[config-file [file!] default-class-name default-fields][
  probe  value? 'class-name
  input
  either (value? 'class-name) [
    probe class-name
  ][
    set 'class-name default-class-name
  ]
]
Ladislav
Thanks Ladislav but it doesn't change the fact that I cannot use funct and so funct is useless for me. Either funct is a shortcut for func /local either it isn't and for me it isn't in my very example.
Rebol Tutorial
It is as *my very example* proves
Ladislav
+1  A: 

I don't think funct behaves differently than func /local. Look at these examples:

>> f: func [/x] [value? 'x]
>> f
== true

I didn't give any value to x, but it says it HAS a value. Same for /local

>> f: func [/local x] [value? 'x]
>> f
== true

Because when you make a variable local (or a refinement) then it means you already set a value for it (which is none) and that is what funct does.

endo64
Well I don't understand why you say it doesn't behave differently since I found an example where it does :)
Rebol Tutorial
But in your first example, there is no set-word, as in your second example: "class-name: default-class-name". funct runs at definition-time not when you call the function. When you use funct and if there is a set-word like "class-name:" then it is already defined as a local variable in your function. Even if you never call the function. And this is exactly the same behavior as func /local. If you put class-name as a /local in your func then it will be the same.
endo64