Hi Dario and Oleg,

After reflection, I think it is not possible to merge with and letrec.
Indeed, since letrec is implemented with an abstraction (as Oleg rightly
pointed out), then any additional definition inside the definition of this
abstraction, will not be visible outside.

In other words, let's imagine that we have an extended letrec allowing also
regular definitions like u and v:

letrec {

'x = exp1;
'y = exp2;
'z = exp3;

u = exp4;
v = exp5;

}

it can be translated into:

with {

bodyrec = \(x,y,z).(exp1, exp2, exp3 with {u=exp4; v=exp5;});
x = bodyrec : _,!,!;
y = bodyrec : !,_,!;
z = bodyrec : !,!,_;

}

but only x, y, z can be seen from outside, not u and v. So, we will have to
find a syntax that makes these limitations very explicit, otherwise, it
will be very confusing for users who will have the same expectations as for
a with.

Yann


Le jeu. 30 juin 2022 à 01:22, Oleg Nesterov <o...@redhat.com> a écrit :

> Hi Dario,
>
> On 06/29, Dario Sanfilippo wrote:
> >
> > On Tue, 28 Jun 2022 at 13:18, Oleg Nesterov <o...@redhat.com> wrote:
> >
> > > Once I was greatly puzzled why letrec doesn't work as I'd expect, and
> > > I had to dig into the compiler sources to understand.
> > >
> > > For example, I think it is not immediately clear why this code
> > >
> > >         process = _ : bug;
> > >
> > >         bug = x,y letrec {
> > >                 'x = _;
> > >                 'y = 0;
> > >         };
> > >
> > > doesn't even compile. IIUC, this is because buildRecursiveBodyDef()
> turns
> > > the code above into something like
> > >
> > >         LETRECBODY = \(x, y).( ... ) ~ (_,_);
> > >         // makeRecProjectionsList()
> > >         x = LETRECBODY : _,!;
> > >         y = LETRECBODY : !,_;
> > >
> >
> > Are there cases where makeRecProjectionList() isn't redundant?
>
> I don't know. Yes I think that compiler could "simply" generate a lambda
> expression, but perhaps I missed something.
>
> At least this is not that simple, I think. OK,
>
>         process = x,y letrec {
>                 'x = expr_x;
>                 'y = expr_y;
>         };
>
> can be translated to
>
>         process = \(x,y).(expr_x, expr_y) ~ (_,_);
>
> But what about
>
>         process = x+y letrec {
>                 'x = expr_x;
>                 'y = expr_y;
>         };
>
> ?
>
> even this trivial case needs some modifications in the compiler, it
> should turn the lambda body into "expr_x + expr_y"...
>
> > As I was telling Yann in another conversation, I was thinking that
> > extending `with` to allow recursive definitions could be a good idea,
>
> I don't know. Personally, I do not think this is that useful, but this
> is just me.
>
> > To get back to the example in my first email, the code
> >
> > onePoleSwitching(att, rel, x) = y
> > with {
> > 'y = (1.0 - coeff) * x + coeff * y;
> > coeff = ba.if(x > y, ba.tau2pole(att), ba.tau2pole(rel));
> > };
> >
> > could be translated into
> >
> > onePoleSwitching(att, rel, x) =
> > \(y).((1.0 - coeff) * x + coeff * y
> > with {
> > coeff = ba.if(x > y, ba.tau2pole(att), ba.tau2pole(rel));
> > }
> > ) ~ _;
> >
> > Does that make sense?
>
> Not sure I understand... Do you mean the compiler can translate the
> 1st variant into the 2nd one? Probably. But you can do it yourself?
>
> I mean, I do not see why do you want "letrec" or "with { 'y = ...; }"
> in this case. I would simply write something like
>
>         onePoleSwitching(att, rel) = func ~ _ with {
>                 func(y, x) = (1.0 - coeff) * x + coeff * y with {
>                         coeff = ...;
>                 };
>         };
>
> To me it looks more clear than the 1st variant, and iiuc it is equivalent
> the 2nd one.
>
> Oleg.
>
>
_______________________________________________
Faudiostream-users mailing list
Faudiostream-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-users

Reply via email to