Jump to page: 1 2
Thread overview
A Tango Fibers question and a functional programming anecdote.
Oct 28, 2007
downs
Oct 28, 2007
downs
Oct 28, 2007
Daniel Keep
Oct 28, 2007
Don Clugston
Oct 28, 2007
Robert Fraser
Oct 28, 2007
Bill Baxter
Oct 28, 2007
BCS
Oct 28, 2007
BCS
Oct 29, 2007
Daniel Keep
Oct 29, 2007
downs
Fake infix operators
Oct 29, 2007
Bill Baxter
Oct 29, 2007
downs
Oct 29, 2007
bearophile
October 28, 2007
Here's a question to the tango devs.
I've been developing my own stackthreads (Fibers basically) library for
a while now, and finally got it working a few days ago.

Then we did some speed tests and discovered that it was about twice as slow as Tango's Fiber implementation.

This prompted me to dig into the Fibers sourcecode, where I discovered that Fibers doesn't backup ECX/EDX on context switch, and the FP registers only on windows.

Now I am confused.

Could a knowledgeable tango dev kindly shed light on this issue? Why isn't it necessary to save all registers on a context switch?

----
Now for the anecdote.
Today, at five in the morning, I wrote what I believe to be the first
purely functional D code with as little redundancy as possible in the
language.

>
> ["Load ", "Prefetch ", "Prefetch "] /zip/ ([0, 1, 2] /map/ (&info
/rfix/ currentComic /fix/ (&subtract!(int) /fix/ currentStrip))) /map/
&concat!(string) /zip/ [&update, &prefetch /fix/ (currentStrip-1),
&prefetch /fix/ (currentStrip-2)] /map/ &Pool.addTask;
>

So I looked at it, and for some _strange_ reason my eyes suddenly
started bleeding heavily.
That's when I knew I had overdone it on the templates again.
:)


PS: Here's the same code with some line breaks. But where's the fun in that?

>
> ["Load ", "Prefetch ", "Prefetch "] /zip/ (
>   [0, 1, 2] /map/ (
>     &info /rfix/ currentComic /fix/ (
>       &subtract!(int) /fix/ currentStrip
>       )
>     )
>   )
>   /map/ &concat!(string) /zip/ [
>     &update,
>     &prefetch /fix/ (currentStrip-1),
>     &prefetch /fix/ (currentStrip-2)
>   ] /map/ &Pool.addTask;
>
October 28, 2007
"downs" <default_357-line@yahoo.de> wrote in message news:fg15ev$12uh$1@digitalmars.com...
> Here's a question to the tango devs.
> I've been developing my own stackthreads (Fibers basically) library for
> a while now, and finally got it working a few days ago.
>
> Then we did some speed tests and discovered that it was about twice as slow as Tango's Fiber implementation.
>
> This prompted me to dig into the Fibers sourcecode, where I discovered that Fibers doesn't backup ECX/EDX on context switch, and the FP registers only on windows.
>
> Now I am confused.
>
> Could a knowledgeable tango dev kindly shed light on this issue? Why isn't it necessary to save all registers on a context switch?

I'm not knowledgeable, but you said ECX/EDX and it triggered something in my brain.  Sure enough, according to the D 1.0 ABI, "EAX, ECX, EDX are scratch registers and can be destroyed by a function."  So they don't have to be preserved because you're allowed to do anything with them.

As for nothing but ST(0-7) being preserved on Windows.. no clue.

>>
>> ["Load ", "Prefetch ", "Prefetch "] /zip/ ([0, 1, 2] /map/ (&info
> /rfix/ currentComic /fix/ (&subtract!(int) /fix/ currentStrip))) /map/
> &concat!(string) /zip/ [&update, &prefetch /fix/ (currentStrip-1),
> &prefetch /fix/ (currentStrip-2)] /map/ &Pool.addTask;

>>
>> ["Load ", "Prefetch ", "Prefetch "] /zip/ (
>>   [0, 1, 2] /map/ (
>>     &info /rfix/ currentComic /fix/ (
>>       &subtract!(int) /fix/ currentStrip
>>       )
>>     )
>>   )
>>   /map/ &concat!(string) /zip/ [
>>     &update,
>>     &prefetch /fix/ (currentStrip-1),
>>     &prefetch /fix/ (currentStrip-2)
>>   ] /map/ &Pool.addTask;
>>

Why/how do you write code like this?  Is it some kind of thing in your brain that makes you think about everything inside out?  Stop it.  Please.  For all our brains' sakes.


October 28, 2007
downs wrote:
> Here's a question to the tango devs.
> I've been developing my own stackthreads (Fibers basically) library for
> a while now, and finally got it working a few days ago.
> 
> Then we did some speed tests and discovered that it was about twice as
> slow as Tango's Fiber implementation.
> 
> This prompted me to dig into the Fibers sourcecode, where I discovered
> that Fibers doesn't backup ECX/EDX on context switch, and the FP
> registers only on windows.
> 
> Now I am confused.
> 
> Could a knowledgeable tango dev kindly shed light on this issue? Why
> isn't it necessary to save all registers on a context switch?
> 
> ----
> Now for the anecdote.
> Today, at five in the morning, I wrote what I believe to be the first
> purely functional D code with as little redundancy as possible in the
> language.
> 
>> ["Load ", "Prefetch ", "Prefetch "] /zip/ ([0, 1, 2] /map/ (&info
> /rfix/ currentComic /fix/ (&subtract!(int) /fix/ currentStrip))) /map/
> &concat!(string) /zip/ [&update, &prefetch /fix/ (currentStrip-1),
> &prefetch /fix/ (currentStrip-2)] /map/ &Pool.addTask;
> 
> So I looked at it, and for some _strange_ reason my eyes suddenly
> started bleeding heavily.
> That's when I knew I had overdone it on the templates again.
> :)

In my best Hercules Grytpype-Thynne voice:
"You silly, twisted boy."

http://www.thegoonshow.net/quotes.asp
October 28, 2007
downs Wrote:

> > ["Load ", "Prefetch ", "Prefetch "] /zip/ ([0, 1, 2] /map/ (&info
> /rfix/ currentComic /fix/ (&subtract!(int) /fix/ currentStrip))) /map/
> &concat!(string) /zip/ [&update, &prefetch /fix/ (currentStrip-1),
> &prefetch /fix/ (currentStrip-2)] /map/ &Pool.addTask;

Ewwww!

That whole create-your-own infix operator thing *is* cool, no doubt, but IMO, it reduces readability. To me:

map(array, &func);

... is more readable than...

array /map/ &func;

... but maybe that's because I've never actually done any functional programming.
October 28, 2007
Jarrett Billingsley wrote:
> I'm not knowledgeable, but you said ECX/EDX and it triggered something in my brain.  Sure enough, according to the D 1.0 ABI, "EAX, ECX, EDX are scratch registers and can be destroyed by a function."  So they don't have to be preserved because you're allowed to do anything with them.
> 

Removed the push for ECX and EDX ( the others are used internally ). It
seems to work. Many thanks! :)

Still runs somewhat slower than Fibers, though. I can't imagine why. Also, oddly, GDC doesn't allow me to push EBP in -O mode and D inline assembly. Works in native GCC assembly. *Very* odd.

> As for nothing but ST(0-7) being preserved on Windows.. no clue.
> 

Aww. Still thanks for answering. I'm sure somebody will know it.

>>> ["Load ", "Prefetch ", "Prefetch "] /zip/ ([0, 1, 2] /map/ (&info
>> /rfix/ currentComic /fix/ (&subtract!(int) /fix/ currentStrip))) /map/
>> &concat!(string) /zip/ [&update, &prefetch /fix/ (currentStrip-1),
>> &prefetch /fix/ (currentStrip-2)] /map/ &Pool.addTask;
> 
>>> ["Load ", "Prefetch ", "Prefetch "] /zip/ (
>>>   [0, 1, 2] /map/ (
>>>     &info /rfix/ currentComic /fix/ (
>>>       &subtract!(int) /fix/ currentStrip
>>>       )
>>>     )
>>>   )
>>>   /map/ &concat!(string) /zip/ [
>>>     &update,
>>>     &prefetch /fix/ (currentStrip-1),
>>>     &prefetch /fix/ (currentStrip-2)
>>>   ] /map/ &Pool.addTask;
>>>
> 
> Why/how do you write code like this?  Is it some kind of thing in your brain that makes you think about everything inside out?  Stop it.  Please.  For all our brains' sakes.
> 
> 

:evil cackle:
Braaaaaaaaaaaaaaains!


Actually, it started out with a piece of code that looked like this

>
> Pool.addTask("Load "~info(), &update);
> Pool.addTask("Prefetch "~info(), &update);
> Pool.addTask("Prefetch "~info(), &update);
>

Clearly, the addTask is redundant here.
I replaced it with

>
> [stuple("Load "~info(), &update), stuple...] /map/ &Pool.addTask;
>

Somebody in IRC pointed out that the stuple was redundant. He must feel horrible for indirectly causing this.

>
> ["Load "~info, ...] /zip/ [&update, ...] /map/ &Pool.addTask;
>

Then I noticed the info calls were also redundant. It went kinda out of control after that. You know the result. :)

 --downs
October 28, 2007

downs wrote:
> Jarrett Billingsley wrote:
>> ...
>> As for nothing but ST(0-7) being preserved on Windows.. no clue.
>>
> 
> Aww. Still thanks for answering. I'm sure somebody will know it.

I think this might be it (from the ABI):

"The FPU stack must be empty when calling a function."

So when it calls the function, the caller will have emptied the FP stack, so there's nothing *in* ST(0-7) to save.

> ...
> 
>> ["Load "~info, ...] /zip/ [&update, ...] /map/ &Pool.addTask;
>>
> 
> Then I noticed the info calls were also redundant. It went kinda out of control after that. You know the result. :)
> 
>  --downs

You're my hero, downs.

	-- Daniel
October 28, 2007
"downs" <default_357-line@yahoo.de> wrote in message news:fg1qhp$22m6$1@digitalmars.com...

> Actually, it started out with a piece of code that looked like this
>
>>
>> Pool.addTask("Load "~info(), &update);
>> Pool.addTask("Prefetch "~info(), &update);
>> Pool.addTask("Prefetch "~info(), &update);

There's an idea for a language feature (off-the-wall and will never get in, but regardless!)

class Pool
{
    void addTask(char[][] names..., void delegate() dgs...)
    {
        // names and dgs should be the same length
        // pairs are in names[i] and dgs[i]
    }
}

Pool.addTask("Load " ~ info(), &update, "Prefetch " ~ info(), &update);

Heee.

I don't see, though, why you couldn't do

void addTask(void delegate()[char[]] tasks) { ... }

Pool.addTask(["Load " ~ info() : &update, "Prefetch " ~ info() : &update]);

>
> Clearly, the addTask is redundant here.
> I replaced it with
>
>>
>> [stuple("Load "~info(), &update), stuple...] /map/ &Pool.addTask;
>>
>
> Somebody in IRC pointed out that the stuple was redundant. He must feel horrible for indirectly causing this.
>
>>
>> ["Load "~info, ...] /zip/ [&update, ...] /map/ &Pool.addTask;
>>
>
> Then I noticed the info calls were also redundant. It went kinda out of control after that. You know the result. :)

Redundancy is not much to worry about, especially if the result of removing it is entirely unreadable.


October 28, 2007
Robert Fraser wrote:
> downs Wrote:
> 
>>> ["Load ", "Prefetch ", "Prefetch "] /zip/ ([0, 1, 2] /map/ (&info
>> /rfix/ currentComic /fix/ (&subtract!(int) /fix/ currentStrip))) /map/
>> &concat!(string) /zip/ [&update, &prefetch /fix/ (currentStrip-1),
>> &prefetch /fix/ (currentStrip-2)] /map/ &Pool.addTask;
> 
> Ewwww!
> 
> That whole create-your-own infix operator thing *is* cool, no doubt, but IMO, it reduces readability. To me:
> 
> map(array, &func);
> 
> ... is more readable than...
> 
> array /map/ &func;
> 
> ... but maybe that's because I've never actually done any functional programming.

The use of infix operators is unrelated to functional programming.  Lisp doesn't have infix operators, for instance.  map(array, &func) is every bit as "functional" as  array /map/ &func.  Or array.map(&func) for that matter.  The functional style part comes from hiding the explicit procedural steps taken by the computer in functions like 'map', and by treating functions like 'func' more as data than code.

--bb
October 28, 2007
Reply to Downs,

>> ["Load ", "Prefetch ", "Prefetch "] /zip/ (
>> [0, 1, 2] /map/ (
>> &info /rfix/ currentComic /fix/ (
>> &subtract!(int) /fix/ currentStrip
>> )
>> )
>> )
>> /map/ &concat!(string) /zip/ [
>> &update,
>> &prefetch /fix/ (currentStrip-1),
>> &prefetch /fix/ (currentStrip-2)
>> ] /map/ &Pool.addTask;

how the heck is that parsing?? Is the /map/ actualy this:

(A / B) / C; ??


October 28, 2007
Reply to Benjamin,

> Reply to Downs,
> 
>>> ["Load ", "Prefetch ", "Prefetch "] /zip/ (
>>> [0, 1, 2] /map/ (
>>> &info /rfix/ currentComic /fix/ (
>>> &subtract!(int) /fix/ currentStrip
>>> )
>>> )
>>> )
>>> /map/ &concat!(string) /zip/ [
>>> &update,
>>> &prefetch /fix/ (currentStrip-1),
>>> &prefetch /fix/ (currentStrip-2)
>>> ] /map/ &Pool.addTask;
> how the heck is that parsing?? Is the /map/ actualy this:
> 
> (A / B) / C; ??
> 

BTW if that is what you are doing, I may be force to do something totally EVIL to reclaim some ground in the "does nasty things with D" ranking. I have a few ideas though....  }:-)  (BBBBWWWWAAAA HAA Haa haaa.....)


« First   ‹ Prev
1 2