Project

General

Profile

Feature #1112

New function: IsEmpty

Added by Anna Maria Bigatti over 6 years ago. Updated 4 months ago.

Status:
Closed
Priority:
Normal
Category:
CoCoA-5 function: new
Target version:
Start date:
27 Oct 2017
Due date:
% Done:

100%

Estimated time:
2.00 h
Spent time:

Description

add function IsEmpty(L) for LIST.


Related issues

Related to CoCoA-5 - Slug #31: theValue makes copyIn Progress2011-11-15

History

#1 Updated by Anna Maria Bigatti almost 4 years ago

  • Target version changed from CoCoA-5.?.? to CoCoA-5.4.0

#2 Updated by John Abbott about 3 years ago

  • Status changed from New to Resolved
  • % Done changed from 0 to 60

I have just added a first impl to BuiltInFunctions.C.
A couple of trivial tests passed.

Still need to: write tests, write doc, modify existing tests/packages (to use IsEmpty instead of comparing to []).

#3 Updated by John Abbott about 3 years ago

The function IsEmpty is slower than explicitly testing for equality to the empty list; why should that be?

Here is the simple test I conducted:

/**/ L := 1..100;
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if IsEmpty(L) then println "*"; endif; endfor; TimeFrom(t0);
0.500
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if L = [] then println "*"; endif; endfor; TimeFrom(t0);
0.390

I tried the test with L := 1..1000000; and the timings were essentially the same.
I suppose I shall have to "play" with the profiler... groan!

#4 Updated by Anna Maria Bigatti about 3 years ago

I made a few tests, and the timings appear to be very similar.
It seems that creating a LIST with the [..] syntax is amazingly cheap:

/**/ t0 := CpuTime();  for j := 1 to 1000000 do skip; endfor; TimeFrom(t0);
0.162 ~ 0.170
t0 := CpuTime();  for j := 1 to 1000000 do if IsEmpty(L) then println "*"; endif; endfor; TimeFrom(t0);
0.662 ~ 0.682
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if L = [] then println "*"; endif; endfor; TimeFrom(t0);
0.628 ~ 0.676
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if L = [9,8] then println "*"; endif; endfor; TimeFrom(t0);
0.869 ~ 0.951

creating [9,8] costs next to nothing.

#5 Updated by John Abbott almost 3 years ago

  • Related to Slug #31: theValue makes copy added

#6 Updated by John Abbott almost 3 years ago

Is this in some way related to issue #31?
If not, delete the link I have just created above.

#7 Updated by Anna Maria Bigatti almost 3 years ago

John Abbott wrote:

Is this in some way related to issue #31?
If not, delete the link I have just created above.

timings are the same, but it's worth thinking a bit longer

/**/ t0 := CpuTime();  for j := 1 to 1000000 do skip; endfor; TimeFrom(t0);
0.172
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if IsEmpty(L) then println "*"; endif; endfor; TimeFrom(t0);
0.640
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if L = [] then println "*"; endif; endfor; TimeFrom(t0);
0.603
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if L = [9,8] then println "*"; endif; endfor; TimeFrom(t0);
0.881

#8 Updated by John Abbott about 2 years ago

  • Target version changed from CoCoA-5.4.0 to CoCoA-5.4.2

#9 Updated by John Abbott about 1 year ago

  • % Done changed from 60 to 80

Mmm, so what is the conclusion here?
Originally I had hoped/expected that a simple built-in function would be faster (and allocate less memory) than
repeatedly creating an empty list. Instead, somehow the function call overhead seems to be greater than any gain.

In the end the difference in speed is pretty unimportant (just rather surprising).

So the real question is: which way gives clearer, more readable code?

  if L = [] then ... endif
  if IsEmpty(L) then ... endif

Maybe we should also consider a more complicated situation:

  if ComplicatedFn(many, args) = [] then ... endif
  if IsEmpty(ComplicatedFn(many, args)) then ... endif

Or even (a weird-looking solution)

  if [] = ComplicatedFn(many, args) then ... endif

It is hard to say. I'm pretty used to = [] but what about newcomers?

Footnote but how often would one do IsEmpty(ComplicatedFn(many,args))?
If it returns a list, we probably want the contents of the list if its not empty.

#10 Updated by John Abbott about 1 year ago

Just out of curiosity I made yet another test:

EMPTY := [];
t0 := CpuTime();  for j := 1 to 1000000 do if L = EMPTY then println "*"; endif; endfor; TimeFrom(t0);

It was almost as "slow" as IsEmpty.

#11 Updated by Anna Maria Bigatti about 1 year ago

And also:

/**/ t0 := CpuTime();  for j := 1 to 1000000 do if IsEven(N) then println "*"; endif; endfor; TimeFrom(t0);
0.659
/**/ t0 := CpuTime();  for j := 1 to 1000000 do if IsEmpty(L) then println "*"; endif; endfor; TimeFrom(t0);
0.630

Now I think the cost is in "function call (variable)"

#12 Updated by Anna Maria Bigatti about 1 year ago

  • Status changed from Resolved to Feedback
  • % Done changed from 80 to 90

In conclusion:
there is no advantage in IsEmpty(L) compared to L = [].
And there is no advantage in removing IsEmpty just because it's not as good as I thought was going to be.

So I would close this issue keeping it, but not encouraging it over "L = []".
I make a minor change in the manual for IsEmpty.

#13 Updated by John Abbott 4 months ago

  • Status changed from Feedback to Closed
  • % Done changed from 90 to 100

The manual entry looks OK to me; what do you think, Anna?
Each user can decide whether they prefer IsEmpty(L) or L = [].
Closing.

Also available in: Atom PDF