Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

Can I define an anti function?

 [1/26] from: lmecir::mbox::vol::cz at: 23-Feb-2004 20:55


Doc draw my attention to the %subject%, which was discussed at comp.lang.scheme. The thread started with: {Suppose f is a function returning a boolean.Is there a way of defining a function anti, which, when given f, returns "not f"?} the discussion continued: {
> > > > (define (anti f) > > > > (lambda args > > > > (not (apply f args)))) > > Why is this objectionable? It provides the ability to do something that > > hardly any other languages can do.
} {
> This last statement is a bit too strong, even in Python you can do
Sheesh, I clearly said "hardly any other languages", not "no other languages". I stand by my original statement -- most programming languages can't do this. Python and Scheme are some of the few that can. C can do it for functions of a specific arity, but can't generalize (e.g. you can write anti_f1 for 1-argument functions, anti_f2 for 2-argument functions, etc.) } { I expect most general-purpose dynamically typed languages can, at least those using a conventional syntax. Perl can, Ruby can (but its treatment of higher orded functions is weird), Dylan can, and probably all Lisp variants too. Smalltalk can't because variable arity doesn't make sense: the method name implies the arity syntactically. Rebol probably can't: here the arity of a function tells how many words to parse as its argument and where the next function call begins. Forth and Postscript can't. Among statically typed languages C# can, and it's the only one I know. } Question: Is the guess about Rebol correct? (I will post my answer later) -L

 [2/26] from: rotenca:telvia:it at: 23-Feb-2004 22:31


My first attempt, but i do not know if it is a right answer: antif: func [:f [any-function!] args[block!]][do head insert copy args :f] --- Ciao Romano

 [3/26] from: rotenca:telvia:it at: 23-Feb-2004 22:53


Obviously I forgot the not. But perhaps i mis-interpreted the syntax required but the antif function. If it is tha case, can you do some examples ot the required syntax? --- Ciao Romano

 [4/26] from: lmecir:mbox:vol:cz at: 24-Feb-2004 2:32


Romano Paolo Tenca napsal(a):
>My first attempt, but i do not know if it is a right answer: > > antif: func [:f [any-function!] args[block!]][do head insert copy args :f] > >--- >Ciao >Romano >
It isn't, because it takes 2 arguments, while ANTI has to take just one: F -L

 [5/26] from: g:santilli:tiscalinet:it at: 24-Feb-2004 12:48


Hi Ladislav, On Monday, February 23, 2004, 8:55:15 PM, you wrote: LM> Question: Is the guess about Rebol correct? (I will post my answer later) At first glance it could seem correct, but it's clearly wrong. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [6/26] from: g:santilli:tiscalinet:it at: 24-Feb-2004 12:50


Hi Ladislav, On Tuesday, February 24, 2004, 2:32:36 AM, you wrote: LM> It isn't, because it takes 2 arguments, while ANTI has to take just one: F .... and return a function. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [7/26] from: andreas:bolka:gmx at: 24-Feb-2004 13:53


Monday, February 23, 2004, 8:55:15 PM, Ladislav wrote:
> Question: Is the guess about Rebol correct? (I will post my answer > later)
I'll second Gabriele's answer: The reasoning seems to be intriguing at first glance, but it's (at least partly) wrong. A (naive) demonstration: anti: func [ f ] [ func first :f compose [ not (second :f) ] ] f: func [ a b ] [ = a b ] anti-f: anti :f f 1 2 ; == false anti-f 1 2 ; == true The above obviously does not cope with functions where 'return is used, however I'm not going into more detail here, as I'm really looking forward to Ladislav's answer (which will be more correct than mine could ever be, anyway). But let me explain why I weakened my above statement with 'at least partly'. In Scheme the following is perfectly legal: (define (anti f) (lambda args (not (apply f args)))) (define (f a b) (equal? a b)) ((anti f) 1 2) ; == #t In REBOL however, my naive approach given above would not give the desired results in this case (anti :f 1 2), as anti :f does not return a "loaded" function, i.e. we'd have to force it's application by using 'do:
>> do anti :f 1 2
== true
>> do anti :f 1 1
== false In my opinion, that is the perfect REBOL equivalent to the special Scheme form used above. However, Scheme purists may argue with me on that point :) Nevertheless, even in Scheme, I imagine the "typical" use of anti would be: (define anti-f (anti f)) -- Best regards, Andreas

 [8/26] from: rotenca:telvia:it at: 24-Feb-2004 14:48


Ok, Lad this is my solution, (without refinements handling and without get and lit arguments and without optimizations) Do not read if you want to try by yourself. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. anti: func [[catch] :f /local body][ body: copy [] parse first :f [ some [ [end | refinement!] break | set x word! (insert insert/only tail body 'get/any to lit-word! x) | (make error! "get and lit arguments not handled") ] ] throw-on-error [make function! first :f head insert insert tail reduce [:not] :f body] ] --- Ciao Romano

 [9/26] from: antonr:iinet:au at: 25-Feb-2004 1:18


What is the purpose and utility of such a function ? Anton.

 [10/26] from: antonr:iinet:au at: 25-Feb-2004 1:34


The function it produces is interesting.
>> f: func [a b][a = b] >> g: anti f >> probe :g
func [a b][native func [a b][a = b] get/any 'a get/any 'b] This 'native function is undocumented and it's not obvious to me what it does. Anton.

 [11/26] from: lmecir:mbox:vol:cz at: 24-Feb-2004 15:55


Hi Romano,
>Ok, Lad > >this is my solution, (without refinements handling and without get and lit >arguments and without optimizations) >
I have got a few notes: 1) I am still not convinced, that a "get argument", (alias "fetched argument") is a good argument passing method. The disadvantage of it is, that you cannot easily supply a result of an expression as an argument. Example: anti func [x [logic!]] [x] ; this is hard to write correctly using the above method No native or mezzanine Core function uses this argument-passing method (although there are natives in Rebol/Core that can take functions as arguments). Allow me to poll other users: how many of you use this argument passing method? anti: func [:f ] [...] 2) Otherwise your solution is very close. The only bug is probably this:
>> f: func [get] [true] >> anti-f: anti f >> anti-f false
** Script Error: Cannot use path on logic! value ** Where: anti-f ** Near: native func [get][true] get/any 'get -L

 [12/26] from: lmecir:mbox:vol:cz at: 24-Feb-2004 16:02


Anton Rolls napsal(a):
>What is the purpose and utility of such a function ? > >Anton. > >>{Suppose f is a function returning a boolean.Is there a way of defining >>a function anti, which, when given f, returns "not f"? >>
This is a higher-order function. This style of programming is known as Functional Programming and some use it in Rebol - cf. Map as an example. Otherwise this specific case is probably just a homework and I brought it here just to show you how some people judge Rebol or other programming languages. -L

 [13/26] from: g:santilli:tiscalinet:it at: 24-Feb-2004 15:58


Hi Anton, On Tuesday, February 24, 2004, 3:34:36 PM, you wrote: AR> func [a b][native func [a b][a = b] get/any 'a get/any 'b] AR> This 'native function is undocumented and it's not obvious AR> to me what it does. What you see is not what you get. ;-) What MOLD prints as "native" above is not the word 'native but the native function NOT.
>> mold reduce [:not]
== "[native]" However, a native called 'NATIVE actually exists,
>> help native
USAGE: NATIVE spec DESCRIPTION: (undocumented) ARGUMENTS: spec -- (Type: block) and as far as I can guess it is used by REBOL components during startup to register new native functions. This is probably a left over, the beta versions don't unset internal functions like older releases did. Regards, Gabriele. -- Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer Amiga Group Italia sez. L'Aquila --- SOON: http://www.rebol.it/

 [14/26] from: lmecir:mbox:vol:cz at: 24-Feb-2004 16:05


Anton Rolls napsal(a):
>The function it produces is interesting. >>>f: func [a b][a = b]
<<quoted lines omitted: 6>>
>to me what it does. >Anton.
that is just the NOT function used as a Rebol value. See this: reduce [:not] ; == [native] -L

 [15/26] from: rotenca:telvia:it at: 24-Feb-2004 16:00


Hi Anton, That is the serialization of a native function referenced directly. In this case happens to be the 'not function. As you can understand, native functions cannot be serialized, and mold put a 'native word for every native it should serialize. It also outputs 'op for every op! and 'action fore every action!:
>> mold reduce [:do :set]
== "[native native]"
>> mold reduce [:equal? :find :add]
== "[action action action]"
>> mold reduce [:+ :-]
== "[op op]" --- Ciao Romano

 [16/26] from: rotenca:telvia:it at: 24-Feb-2004 17:05


Hi Lad,
> I have got a few notes: > > 1) I am still not convinced, that a "get argument", (alias "fetched > argument") is a good argument passing method. The disadvantage of it is, > that you cannot easily supply a result of an expression as an argument.
yes, but it is so elegant to write anti equal? instead of anti :equal? but i agree, the :arg notation is never used and it requires a reference to a value instead of the "value itself", so it is not totally "correct" to be used it in context like this. About Scheme people, if they would speak "in general", they could be right: we cannot create an anti :do and anti :make which work in every situations, but if they speak only of strict bolean functions, i think they are wrong ;-)
> 2) Otherwise your solution is very close. The only bug is probably this: > >> f: func [get] [true]
<<quoted lines omitted: 3>>
> ** Where: anti-f > ** Near: native func [get][true] get/any 'get
yes, i forgot to delay the get/any insertion after the bind to the function context. there are many modes to do it, and this is one of them: .. .. .. .. .. .. .. .. .. .. .. .. .. .. anti: func [[catch] f /local body x][ insert insert tail body: make block! 2 + length? first :f :not :f parse first :f [ any [ [end | refinement!] break | set x word! (insert tail body to lit-word! x) | (make error! "get and lit arguments not handled") ] ] x: next next second f: throw-on-error [make function! first :f body] while [not tail? x][x: next insert/only x 'get/any] :f ] --- Ciao Romano

 [17/26] from: maximo:meteorstudios at: 24-Feb-2004 11:15


you could use my encompass function to create an anti function. It would even handle all the refinements transparently and would map all parameters, without you needing to know the function's actual argument block. -MAx --- You can either be part of the problem or part of the solution, but in the end, being part of the problem is much more fun.

 [18/26] from: lmecir:mbox:vol:cz at: 24-Feb-2004 17:55


Hi Romano,
>...but i agree, the :arg notation is never used and it requires a reference to a >value instead of the "value itself", so it is not totally "correct" to be used >it in context like this. > >About Scheme people, if they would speak "in general", they could be right: we >cannot create an anti :do and anti :make which work in every situations, but >if they speak only of strict bolean functions, i think they are wrong ;-) >
That's the point I was prepared to make :-) If we translate "a function returning boolean" to Rebol as a function always returning Logic! (for any input), then we are safe as you said, because DO (as well as MAKE) sometimes return different datatypes.
>... >yes, i forgot to delay the get/any insertion after the bind to the function >context. > >there are many modes to do it, and this is one of them: >
.... yes. To present a solution, that looks as simple as possible, we can write: anti: func [f [any-function!] /local exec] [ exec: func [block] reduce ['not 'apply 'first reduce [:f] 'block] func load mold third :f reduce [:exec first :f] ] , where the only missing part is an APPLY function, which takes a block of words and passes their values to the function. An easy ;-) exercise for the reader. -L

 [19/26] from: lmecir:mbox:vol:cz at: 24-Feb-2004 18:23


Maxim Olivier-Adlhoch napsal(a):
>you could use my encompass function to create an anti function. >
...., but it wouldn't work for some cases. Have a look at http://www.compkarori.com/vanilla/display/subfunc.r , which does (essentially) the same thing ;-) and is optimized for speed by Romano (I recently found that some improvements can still be made - 67% speed-up and a correction for unevaluated argument passing) -L

 [20/26] from: maximo:meteorstudios at: 24-Feb-2004 12:32


> anti: func [f [any-function!] /local exec] [ > exec: func [block] reduce ['not 'apply 'first reduce [:f] 'block] > func load mold third :f reduce [:exec first :f] > ] >
that's basically what encompass does including all refinements and their values. you can even augment the argument list and refinements if you want additional features. encompass.r in on the rebol.org site. and is alson included in the slim tool. basically you'd do: myfunc: func [obj word][either in obj word [true][false]] anti-func: encompass/post 'myfunc [rval: not rval] maybe I'm missing the point... as some theory about previous posts is escaping me a little... but for any boolean function, this definitely should work. cheers! -MAx

 [21/26] from: maximo:meteorstudios at: 24-Feb-2004 12:46


Ladislav Wrote:
> >you could use my encompass function to create an anti function. > >
<<quoted lines omitted: 6>>
> speed-up > and a correction for unevaluated argument passing)
hum... If I had a few spare hours, I'd dive in and do some serious checking, I really like this kind of analysis... but I really have no time currently, I have too much to do... thanks for letting me know (reminding me?) it exists... If I get into troubles, I'll surely check out your function to see how it solves specific issues my solution (might/surely) has. the only notable advantage that I can see emcompass having, is in its form, where its all packaged into one function with no dependencies, but you could easily repackage subfunc to do that too... so my point is rather moot ;-) I've never tried to make encompass go faster, since I wanted to code to be readable for novice/intermediate users. also notice that it is EXTREMELY documented... which possibly could make it easy to improve... alternatives are always nice :-) cheers! -MAx

 [22/26] from: rotenca:telvia:it at: 24-Feb-2004 18:48


> ..., but it wouldn't work for some cases. Have a look at > http://www.compkarori.com/vanilla/display/subfunc.r , which does > (essentially) the same thing ;-) and is optimized for speed by Romano (I > recently found that some improvements can still be made - 67% speed-up > and a correction for unevaluated argument passing)
Well! Don't you publish it? --- Ciao Romano

 [23/26] from: tomc:darkwing:uoregon at: 24-Feb-2004 11:10


how bout ... antif: func [fn-args[block!]][not do fn-args] then anitif [fn args1 argn] On Mon, 23 Feb 2004, Ladislav Mecir wrote:

 [24/26] from: lmecir:mbox:vol:cz at: 25-Feb-2004 21:28


Tom Conlin napsal(a):
>how bout ... > >antif: func [fn-args[block!]][not do fn-args] > >then > >anitif [fn args1 argn] >
That doesn't correspond to the specification -L

 [25/26] from: antonr:iinet:au at: 27-Feb-2004 1:20


Hi Ladislav. I don't think I've ever used that way. Anton.

 [26/26] from: maximo:meteorstudios at: 26-Feb-2004 10:49


I have, on occasion, but its not something that is needed very often. I think most of these kind of things are mainly used by those of us who build tools, apis and things of the sort. This really isn't the majority IMO. -MAx --- You can either be part of the problem or part of the solution, but in the end, being part of the problem is much more fun.

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted