Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Generalized tagRec?
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  8 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Artyom Shalkhakov  
View profile  
 More options Jun 4, 7:05 am
From: Artyom Shalkhakov <artyom.shalkha...@gmail.com>
Date: Thu, 4 Jun 2009 17:05:16 +0600
Local: Thurs, Jun 4 2009 7:05 am
Subject: Generalized tagRec?
Hello,

I was writing a small file browser in Flapjax and have encountered
a problem with tagRec: there seems to be no way to make one
dynamically created tag to depend on another dynamically created
tag's events.

What I would like to achieve is a tree with branches that
can be shown or hidden.

The tree (or rather, a forest) for testing is the parse tree of an expression
a + b * c, which is translated to JS as follows:

> [{label: 'plus', children: [
>       {label: 'a', children: []},
>       {label: 'multiply', children: [
>            {label: 'b',children: []},
>            {label: 'c',children: []}]}]}]

Here's how it is converted to HTML:

> // fun :: Forest * Maybe Hash -> Dom
> function fun(y,vis) {
>     return UL(vis || {}, map(function(x) {
>          return tagRec(['click'],
>              function(e) {
>                  var db = toggleE('block','none',e).startsWith('block');
>                  return LI(A({href:'#'+x.label},x.label),
>                                 fun(x.children, {style: {display: db}}));
>              });
>     }, y));
> }

toggleE is defined as follows:

> function toggleE(a,b,e) {
>    return e.collectE(true, function(_,y) {
>        return !y;
>    }).mapE(function(x) {return x? a : b;});
> }

The tree behaves unexpectedly, because tagRec reacts to *all*
events happening inside a LI, while it should only react to events
of A.

I think I can come up with a hack but would like to write in the
most obvious (and declarative :-)) way possible.

Could anybody help me, please?

Cheers,
Artyom Shalkhakov.

PS here's a demo: http://www.sound-city.kz/fj/tree.html


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Artyom Shalkhakov  
View profile  
 More options Jun 5, 7:53 am
From: Artyom Shalkhakov <artyom.shalkha...@gmail.com>
Date: Fri, 5 Jun 2009 17:53:27 +0600
Local: Fri, Jun 5 2009 7:53 am
Subject: Re: Generalized tagRec?
2009/6/4 Artyom Shalkhakov <artyom.shalkha...@gmail.com>:

Suddenly I've found a solution which works okay and is still very nice.

Here it is:

> function fun(y,vis) {
>   return UL(vis || {}, map(function(x) {
>     var a = A({href:'#'+x.label},x.label);
>     var db = toggleE('block','none',clicksE(a)).startsWith('block');
>     return LI(a, fun(x.children,{style:{display:db}}));
>   }, y));
> }

Strangely enough I got it working without any debugging at all, woot! :)

Cheers,
Artyom Shalkhakov.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Arjun Guha  
View profile  
 More options Jun 5, 8:02 am
From: Arjun Guha <arjun.g...@gmail.com>
Date: Fri, 5 Jun 2009 08:02:09 -0400
Local: Fri, Jun 5 2009 8:02 am
Subject: Re: [Flapjax: 429] Re: Generalized tagRec?
Looking at your solution, you didn't actually need a generalized
tagRec since you had a 1-way dependency.  However, there are cases
when you want a pair of tags to depend on events from each other.  For
that, a generalized tagRec would be great.

Maybe one of the implementors will add it out soon.

Arjun

On Fri, Jun 5, 2009 at 07:53, Artyom Shalkhakov


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jacob Baskin  
View profile  
 More options Jun 5, 8:44 am
From: Jacob Baskin <goingo...@gmail.com>
Date: Fri, 5 Jun 2009 08:44:20 -0400
Local: Fri, Jun 5 2009 8:44 am
Subject: Re: [Flapjax: 431] Re: Generalized tagRec?
I made a construct called rec_e for similar tasks in Continue/Resume:

rec_e :: (Event A -> Event A) -> Event A

It takes a function from events to events, and calls it in such a way that the
event stream it returns and the event stream it takes are "the same"
(naturally, they aren't actually the same, they just fire at the same time).
Then it also returns this event stream. It can be defined thus:

function rec_e(fn) {
  var inE = receiver_e();
  var outE = fn(inE);
  outE.transform_e(function(_) {
    inE.sendEvent(_);
  });
  return outE;

}

On 6/5/09, Arjun Guha <arjun.g...@gmail.com> wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Artyom Shalkhakov  
View profile  
 More options Jun 12, 6:16 am
From: Artyom Shalkhakov <artyom.shalkha...@gmail.com>
Date: Fri, 12 Jun 2009 16:16:28 +0600
Local: Fri, Jun 12 2009 6:16 am
Subject: Re: [Flapjax: 431] Re: Generalized tagRec?
Hi,

Sorry for the delay.

2009/6/5 Arjun Guha <arjun.g...@gmail.com>:

> Looking at your solution, you didn't actually need a generalized
> tagRec since you had a 1-way dependency.  However, there are cases
> when you want a pair of tags to depend on events from each other.  For
> that, a generalized tagRec would be great.

I have found a simple example where you need a generalized tagRec.
(Actually, I need to solve this problem to continue with my current
project.)

Let's say we have two links (buttons, tabs...) "A" and "B" and we want
one of them to be "focused" (or "selected"). Focusing a link, as well as
"unfocusing" it, should change it's color accordingly.

If we had Scheme's letrec in JS, the solution would look as follows:

> letrec a = A({href:'#', style:{color:
>                     startsWith(mergeE(ev1.constantE('#777'),
>                                                     ev2.constantE('#000')),
>                                       '#000')}}, "this is A")
>           b = A({href:'#', style:{color:
>                    startsWith(mergeE(ev1.constantE('#000'),
>                                                    ev2.constantE('#777')),
>                                      '#000')}}, "this is B")
>           ev1 = clicksE(a)
>           ev2 = clicksE(b)
> in UL(LI(a),LI(b))

How to do this in JS? The best solution I found involves tricky assignments
and effectful event streams.

I don't get how a menu (either hierarchical or not), a tabbed navigation,
etc. could be implemented without such cyclic dependencies. We could
do it imperatively, of course...

> Maybe one of the implementors will add it out soon.

Let's hope for the better then. :)

Cheers,
Artyom Shalkhakov.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Artyom Shalkhakov  
View profile  
 More options Jun 12, 6:18 am
From: Artyom Shalkhakov <artyom.shalkha...@gmail.com>
Date: Fri, 12 Jun 2009 16:18:46 +0600
Local: Fri, Jun 12 2009 6:18 am
Subject: Re: [Flapjax: 432] Re: Generalized tagRec?
Hi,

That's cool, but I couldn't adapt it to the problem at hand. Care
to elaborate?

Cheers,
Artyom Shalkhakov.

2009/6/5 Jacob Baskin <goingo...@gmail.com>:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Jacob Baskin  
View profile  
 More options Jun 12, 8:02 am
From: Jacob Baskin <goingo...@gmail.com>
Date: Fri, 12 Jun 2009 08:02:34 -0400
Local: Fri, Jun 12 2009 8:02 am
Subject: Re: [Flapjax: 434] Re: Generalized tagRec?
On Friday 12 June 2009, Artyom Shalkhakov wrote:

> Hi,

> That's cool, but I couldn't adapt it to the problem at hand. Care
> to elaborate?

Sure.  Rather than:

> letrec a = A({href:'#', style:{color:
>                     startsWith(mergeE(ev1.constantE('#777'),
>                                                     ev2.constantE('#000')),
>                                       '#000')}}, "this is A")
>           b = A({href:'#', style:{color:
>                    startsWith(mergeE(ev1.constantE('#000'),
>                                                    ev2.constantE('#777')),
>                                      '#000')}}, "this is B")
>           ev1 = clicksE(a)
>           ev2 = clicksE(b)
> in UL(LI(a),LI(b))

Just do:

var list = null;

rec_e(function(clicks) {
  var b_clicks = clicks.transform_e(
    function(_) { return _ == '#000' ? '#777' : '#000'; });
  var a = A({href:'#', style:{color: clicks.startsWith('#000')},
                   'this is A');
  var b = A({href:'#', style:{color: b_clicks.startsWith('#000')},
                   'this is B');
  list = UL(LI(a),LI(b));
  return merge_e(clicksE(a).constant_e('#777'),
                            clicksE(b).constant_e('#000'));

});

The basic idea is that it's easy to write down the event stream you want at
the end of a function. We just need to get it back to the beginning of the
function and you can do anything you want. So that's what rec_e does--it takes
an event stream from the end of the function and feeds it back in at the
start.

Looking at this example, there's probably a more useful signature that would
let you return both the event stream you want to pass back and also another
return value (that becomes the return value of rec_e). That way, you could
just do

return [merge_e(clicksE(a).constant_e('#777'),
                            clicksE(b).constant_e('#000')),
            UL(LI(a),LI(b))];

instead of doing the ugliness with the outer-scope variable to get the other
value out. This would just be:

function rec_e(fn) {
  var inE = receiver_e();
  var ret = fn(inE);
  var outE = ret[0];
  outE.transform_e(function(_) {
    inE.sendEvent(_);
  });
  return ret[1];

}

And the signature would be:

rec_e :: (Event A -> [Event A, B]) -> B

Make sense?


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Artyom Shalkhakov  
View profile  
 More options Jun 13, 3:19 am
From: Artyom Shalkhakov <artyom.shalkha...@gmail.com>
Date: Sat, 13 Jun 2009 13:19:35 +0600
Local: Sat, Jun 13 2009 3:19 am
Subject: Re: [Flapjax: 435] Re: Generalized tagRec?
2009/6/12 Jacob Baskin <goingo...@gmail.com>:

> Just do:

> var list = null;

> rec_e(function(clicks) {
>  var b_clicks = clicks.transform_e(
>    function(_) { return _ == '#000' ? '#777' : '#000'; });
>  var a = A({href:'#', style:{color: clicks.startsWith('#000')},
>                   'this is A');
>  var b = A({href:'#', style:{color: b_clicks.startsWith('#000')},
>                   'this is B');
>  list = UL(LI(a),LI(b));
>  return merge_e(clicksE(a).constant_e('#777'),
>                            clicksE(b).constant_e('#000'));
> });

Simply great. :)

> Make sense?

Yes. Big thanks for the explanation.

Cheers,
Artyom Shalkhakov.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google