<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hi, Richard,<div class=""><br class=""></div><div class="">Thanks for explaining the fascinating tradition behind append/1 in Lisp and Prolog. </div><div class=""><br class=""></div><div class="">I totally agree with you on the simplicity and performance aspect of append/1 and append/2. I doesn’t make sense at all to add the O(n) check for “proper list”.</div><div class=""><br class=""></div><div class="">I remember when I was following a beginner tutorial on Prolog, I’ve found the append/1 confused me same as Karlo.  I think most people including me is confused append/1 with something like flat (not lists:flatten/1) or chain in other languages like the the new addition: flat method of Array in Javascript:</div><div class=""><br class="">>[[1, 2], 3].flat()<br class=""> [1, 2, 3]<br class=""><br class="">>[[1, [2]], 3].flat()<br class="">[1, [2], 3]<br class=""><br class="">>[1].flat()<br class="">[1]<br class=""><br class="">>[].flat()<br class="">[]<br class=""><br class="">it only “flat” once instead “flat” all the way like erlang lists:flatten/1 does<br class=""><br class="">I think it fit to into people’s mindset about “flat once” of an ordered collection and return the same type.<br class=""><br class="">simple implementation in erlang would be:<br class=""><br class="">flat([]) -> [];<br class="">flat([[]|T]) -> flat(T);<br class="">flat([[H1|T1]|T]) -> [H1|flat([T1|T])];<br class="">flat([H|T]) -> [H|flat(T)].<br class=""><br class="">>flat([[1,2],3]).<br class="">[1,2,3]<br class=""><br class="">>flat([[1, [2]], 3]).<br class="">[1,[2],3]<br class=""><br class="">>flat([1]).<br class="">[1]<br class=""><br class="">>flat([]).<br class="">[].<br class=""><br class="">The only thing inconsistent is that as you pointed out several times there's no easy way to check the list is a “proper list” without walking to the end of the list, <br class=""><br class="">> flat([1|2]).<br class="">** exception error: no function clause matching lists2:flat(2) <br class=""><br class="">but I think it’s ok to skip the “proper list” checking and let dialyzer or programmer handle it as you suggested, and so maybe it’s good to add flat/1 to the lists module and make it a clear separation  of append/1 and  flat/1 which maybe a concept a lot of programmer already familiar with .<br class=""><br class="">mko<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On 19/09/2019, at 8:29 PM, Richard O'Keefe <<a href="mailto:raoknz@gmail.com" class="">raoknz@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="gmail_default" style="font-family:monospace,monospace">"Not checking for whether something is a properly formed list (the whole <br class="">
objection some have is that append/2 should be able to accept an <br class="">
improper list as the second argument) but merely checking whether the <br class="">
second argument is a list of any form at all."</div><div class="gmail_default" style="font-family:monospace,monospace"><br class=""></div><div class="gmail_default" style="font-family:monospace,monospace">But what the heck is the point of *that*?</div><div class="gmail_default" style="font-family:monospace,monospace">Why is it important for  [a] ++ c to fail</div><div class="gmail_default" style="font-family:monospace,monospace">but OK for [a] ++ [b|c] to succeed?</div><div class="gmail_default" style="font-family:monospace,monospace">I'm sorry, but that makes no sense to me at all.</div><div class="gmail_default" style="font-family:monospace,monospace"><br class=""></div><div class="gmail_default" style="font-family:monospace,monospace"><br class=""></div><div class="gmail_default" style="font-family:monospace,monospace"><br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, 19 Sep 2019 at 18:58, zxq9 <<a href="mailto:zxq9@zxq9.com" class="">zxq9@zxq9.com</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 2019/09/19 10:33, Richard O'Keefe wrote:<br class="">
> I'm sorry, but what O(1) runtime check are we talking about here?<br class="">
> I don't know of any O(1) way to test "is this a proper list" in<br class="">
> Erlang.<br class="">
<br class="">
Not checking for whether something is a properly formed list (the whole <br class="">
objection some have is that append/2 should be able to accept an <br class="">
improper list as the second argument) but merely checking whether the <br class="">
second argument is a list of any form at all.<br class="">
<br class="">
A single is_list/1 check guarding the leading clause can do that.<br class="">
<br class="">
The discussion has gone through:<br class="">
<br class="">
A1: "The typespec says both arguments must be lists"<br class="">
B1: "Use Dialyzer"<br class="">
<br class="">
A2: "The check should be dynamic at runtime"<br class="">
B2: "Checking for *proper* lists is too much overhead"<br class="">
<br class="">
A3: "We should accept improper lists as a second argument"<br class="">
B3: "Then is_list/2 could check the 2nd arg on entry only"<br class="">
<br class="">
A4: "Some people use append/2 to *construct* improper lists"<br class="">
B4: "Then why do we even have a typespec at all?"<br class="">
<br class="">
My position is that B2 and A3 are valid, and B3 is a reasonable <br class="">
compromise that shouldn't break legacy code. I think A4 is unreasonably <br class="">
inconsistent, though, and would wonder why we're even going to have a <br class="">
typespec.<br class="">
<br class="">
-Craig<br class="">
</blockquote></div>
_______________________________________________<br class="">erlang-questions mailing list<br class=""><a href="mailto:erlang-questions@erlang.org" class="">erlang-questions@erlang.org</a><br class="">http://erlang.org/mailman/listinfo/erlang-questions<br class=""></div></blockquote></div><br class=""></div></body></html>