Re: junctions and parenthesis
Patrick R. Michaud wrote: > The "any" function is just like any other function taking an arbitrary list > of arguments (including user-defined functions). As such it parses with > lower precedence than comparison operators -- so "eq" binds more tightly > than "any". Thanks, makes sense. > I'm not exactly sure what sort of warning should go here, or how it'd be > detected. Yes, exactly. From one point of view it's working as designed-- to me it felt pretty weird, though. Speculating wildly: could there be a need for a different type of function with different precedence? On 6/21/20, Patrick R. Michaud wrote: > The "any" function is just like any other function taking an arbitrary list > of arguments (including user-defined functions). As such it parses with > lower precedence than comparison operators -- so "eq" binds more tightly > than "any". > > Thus > >say so any eq any ; > > parses like > >say(so(any( eq any(; > > which is indeed False. > > I'm not exactly sure what sort of warning should go here, or how it'd be > detected. But perhaps others have ideas. > > Pm > > > On Sun, Jun 21, 2020 at 07:00:23PM -0700, Joseph Brenner wrote: >> I was just playing around with junctions a bit today, and I >> noticed that if you weren't religious about using parenthesis >> with them you could get quietly tripped up: >> >> say so any() eq any(); # True (as expected) >> say so any() eq any(); # False (as expected) >> say so any eq any ; # False(something's wrong) >> >> Basically, you need the parens on that first use of any. >> >> Is there a reason you don't at least get a warning if you don't? >
Re: junctions and parenthesis
On Mon, 22 Jun 2020, Joseph Brenner wrote: > Patrick R. Michaud wrote: > > > The "any" function is just like any other function taking an arbitrary list > > of arguments (including user-defined functions). As such it parses with > > lower precedence than comparison operators -- so "eq" binds more tightly > > than "any". > > Thanks, makes sense. > > > I'm not exactly sure what sort of warning should go here, or how it'd be > > detected. > > Yes, exactly. From one point of view it's working as designed-- to me > it felt pretty weird, though. > > Speculating wildly: could there be a need for a different type of > function with different precedence? > You can achieve this today by redefining &any to be a prefix operator and provide it with tight enough precedence. In this example, I pick infix multiplication as the argument stopper, which is in particular tighter than the relevant eq operator; your mileage may vary: sub old-any (|c) { CORE::{'&any'}.(|c) } multi prefix: (|c) is tighter(&infix:<*>) { old-any |c } say so any eq any ;# True (fixed) say so old-any() eq old-any(); # True say so old-any eq old-any ; # False Now I'd be interested to see how someone would turn this into a frugal-sub declarator or an `is frugal` trait. Regards, Tobias -- "There's an old saying: Don't change anything... ever!" -- Mr. Monk
Re: junctions and parenthesis
BEGIN trait_mod:(&any, :tighter(&infix:<*>)); comes to mind, but that doesn't seem to do the trick. > On 22 Jun 2020, at 21:11, Tobias Boege wrote: > > On Mon, 22 Jun 2020, Joseph Brenner wrote: >> Patrick R. Michaud wrote: >> >>> The "any" function is just like any other function taking an arbitrary list >>> of arguments (including user-defined functions). As such it parses with >>> lower precedence than comparison operators -- so "eq" binds more tightly >>> than "any". >> >> Thanks, makes sense. >> >>> I'm not exactly sure what sort of warning should go here, or how it'd be >>> detected. >> >> Yes, exactly. From one point of view it's working as designed-- to me >> it felt pretty weird, though. >> >> Speculating wildly: could there be a need for a different type of >> function with different precedence? >> > > You can achieve this today by redefining &any to be a prefix operator > and provide it with tight enough precedence. In this example, I pick > infix multiplication as the argument stopper, which is in particular > tighter than the relevant eq operator; your mileage may vary: > > sub old-any (|c) { CORE::{'&any'}.(|c) } > > multi prefix: (|c) is tighter(&infix:<*>) { > old-any |c > } > > say so any eq any ;# True (fixed) > say so old-any() eq old-any(); # True > say so old-any eq old-any ; # False > > Now I'd be interested to see how someone would turn this into a > frugal-sub declarator or an `is frugal` trait. > > Regards, > Tobias > > -- > "There's an old saying: Don't change anything... ever!" -- Mr. Monk
Re: junctions and parenthesis
On Mon, 22 Jun 2020, Elizabeth Mattijsen wrote: > BEGIN trait_mod:(&any, :tighter(&infix:<*>)); > > comes to mind, but that doesn't seem to do the trick. > My guess: tighter and looser are only consulted by the parser in contexts where 'any' was recognized as an *operator*.
why so different
Hi all, First, I'm naive in Raku. Then let's go to my question. I'm trying to figure out why we got so different results here: > e.Rat()**(pi.Rat()*i) -0.9902-1.3942922582021257e-07i > e**(pi*i) -1+1.2246467991473532e-16i > e.Rat()**(pi.Rat()*i) == e**(pi*i) False I understand the Num actually have the traditional behavior which leads this: 0.1.Num() + 0.2.Num() != 0.3.Num() And Rat is awesome cos deal nice to the real world. Anyway, I do not expect so different results between Rat and Num. Thanks, Aureliano Guedes -- Aureliano Guedes skype: aureliano.guedes contato: (11) 94292-6110 whatsapp +5511942926110
Re: why so different
On Mon, 22 Jun 2020, Aureliano Guedes wrote: > Hi all, > > First, I'm naive in Raku. Then let's go to my question. > > I'm trying to figure out why we got so different results here: > > > e.Rat()**(pi.Rat()*i) > -0.9902-1.3942922582021257e-07i > > e**(pi*i) > -1+1.2246467991473532e-16i > > e.Rat()**(pi.Rat()*i) == e**(pi*i) > False > > I understand the Num actually have the traditional behavior which leads > this: > 0.1.Num() + 0.2.Num() != 0.3.Num() > > And Rat is awesome cos deal nice to the real world. > > Anyway, I do not expect so different results between Rat and Num. > First, e and π are not rational numbers, so Num (IEEE 754 double) and Rat (pair of bigint numerator and denominator) both will be only approximations. The literals e and pi in Raku are typed as Num and when you call the Rat method on them, you get a Rat back with the *default* precision of 1e-6 [1]. That is a lot less precise than the Nums you started with, hence the difference. Try supplying a large enough precision: > e.Rat(1e-200)**(pi.Rat(1e-200)*i) -1+1.2246467991473532e-16i This is better than a default .Rat() but notice that you cannot get past the limited precision in the source Nums, which is ca. 1e-16. Best, Tobias [1] https://docs.raku.org/routine/Rat -- "There's an old saying: Don't change anything... ever!" -- Mr. Monk
Re: why so different
Thank you for the clarification. There is a method to set Rat precision at the scope of the program to apply to all *.Rat() cases? On Mon, Jun 22, 2020 at 5:57 PM Tobias Boege wrote: > On Mon, 22 Jun 2020, Aureliano Guedes wrote: > > Hi all, > > > > First, I'm naive in Raku. Then let's go to my question. > > > > I'm trying to figure out why we got so different results here: > > > > > e.Rat()**(pi.Rat()*i) > > -0.9902-1.3942922582021257e-07i > > > e**(pi*i) > > -1+1.2246467991473532e-16i > > > e.Rat()**(pi.Rat()*i) == e**(pi*i) > > False > > > > I understand the Num actually have the traditional behavior which leads > > this: > > 0.1.Num() + 0.2.Num() != 0.3.Num() > > > > And Rat is awesome cos deal nice to the real world. > > > > Anyway, I do not expect so different results between Rat and Num. > > > > First, e and π are not rational numbers, so Num (IEEE 754 double) > and Rat (pair of bigint numerator and denominator) both will be only > approximations. > > The literals e and pi in Raku are typed as Num and when you call the > Rat method on them, you get a Rat back with the *default* precision > of 1e-6 [1]. That is a lot less precise than the Nums you started > with, hence the difference. Try supplying a large enough precision: > > > e.Rat(1e-200)**(pi.Rat(1e-200)*i) > -1+1.2246467991473532e-16i > > This is better than a default .Rat() but notice that you cannot get > past the limited precision in the source Nums, which is ca. 1e-16. > > Best, > Tobias > > [1] https://docs.raku.org/routine/Rat > > -- > "There's an old saying: Don't change anything... ever!" -- Mr. Monk > -- Aureliano Guedes skype: aureliano.guedes contato: (11) 94292-6110 whatsapp +5511942926110
Re: why so different
On Mon, 22 Jun 2020, Aureliano Guedes wrote: > Thank you for the clarification. > > There is a method to set Rat precision at the scope of the program to apply > to all *.Rat() cases? > I don't know, based on a quick search in the documentation, of any global setting. The hacky solution would be to wrap the method like this: say pi.Rat.nude; # OUTPUT: (355 113) Num.^find_method('Rat').wrap: -> |c { # Make the default argument 1e-20 callwith |(|c, 1e-20 if c.elems ≤ 1) }; say pi.Rat.nude; # OUTPUT: (245850922 78256779) This program has three parts. First, we print pi.Rat.nude for comparison. The nude method returns numerator and denominator of a Rat as a list. The last part is just looking at pi.Rat.nude again to confirm that the change in the middle has worked and increased the default precision. You said you are relatively new to Raku, so let me explain the middle part. Raku has a special syntax for calling metamethods (i.e. doing introspection) on an object or type, which is the .^ operator. I use it to access an object representation of the Rat method on the Num type. I can wrap some code of my liking around this method via its wrap method. The `-> |c { … }` syntax creates an anonymous code block that wraps around the Num.Rat method and it accepts all arguments that may be passed as a Capture [1] in the variable c. If that Capture does not have a first parameter, i.e. the precision is not specified, I sneak in my 1e-20. Afterwards, the `callwith |(…)` part unpacks the (modified) captured arguments and calls the original method that I am wrapping [2]. Effectively, I pass a precision of 1e-20 whenever the caller did not pass a precision. You can see that the wrapping takes effect immediately in the last line of the above program. Ideally, this could be turned into a module that hides the questionable means behind a dynamic $*RAT-PRECISION variable or so. That is, unless someone comes up with an even better solution. Best, Tobias [1] https://docs.raku.org/type/Capture [2] https://docs.raku.org/routine/wrap -- "There's an old saying: Don't change anything... ever!" -- Mr. Monk
Re: why so different
Thanks again. I'm trying to get proficiency in Raku by converting some Python programs mine in Raku. On Mon, Jun 22, 2020 at 6:41 PM Tobias Boege wrote: > On Mon, 22 Jun 2020, Aureliano Guedes wrote: > > Thank you for the clarification. > > > > There is a method to set Rat precision at the scope of the program to > apply > > to all *.Rat() cases? > > > > I don't know, based on a quick search in the documentation, of any global > setting. The hacky solution would be to wrap the method like this: > > say pi.Rat.nude; # OUTPUT: (355 113) > > Num.^find_method('Rat').wrap: -> |c { > # Make the default argument 1e-20 > callwith |(|c, 1e-20 if c.elems ≤ 1) > }; > > say pi.Rat.nude; # OUTPUT: (245850922 78256779) > > This program has three parts. First, we print pi.Rat.nude for comparison. > The nude method returns numerator and denominator of a Rat as a list. > The last part is just looking at pi.Rat.nude again to confirm that the > change in the middle has worked and increased the default precision. > > You said you are relatively new to Raku, so let me explain the middle part. > Raku has a special syntax for calling metamethods (i.e. doing > introspection) > on an object or type, which is the .^ operator. I use it to access an > object > representation of the Rat method on the Num type. I can wrap some code of > my liking around this method via its wrap method. > > The `-> |c { … }` syntax creates an anonymous code block that wraps around > the Num.Rat method and it accepts all arguments that may be passed as a > Capture [1] in the variable c. If that Capture does not have a first > parameter, i.e. the precision is not specified, I sneak in my 1e-20. > Afterwards, the `callwith |(…)` part unpacks the (modified) captured > arguments and calls the original method that I am wrapping [2]. > > Effectively, I pass a precision of 1e-20 whenever the caller did not pass > a precision. You can see that the wrapping takes effect immediately in > the last line of the above program. > > Ideally, this could be turned into a module that hides the questionable > means behind a dynamic $*RAT-PRECISION variable or so. That is, unless > someone comes up with an even better solution. > > Best, > Tobias > > [1] https://docs.raku.org/type/Capture > [2] https://docs.raku.org/routine/wrap > > -- > "There's an old saying: Don't change anything... ever!" -- Mr. Monk > -- Aureliano Guedes skype: aureliano.guedes contato: (11) 94292-6110 whatsapp +5511942926110