I often write things the way you do. I find that it=
39;s easier to test if I can get at as many procedures as possible from the=
REPL (but maybe I'm not very Schemey either). I also find it harder to=
read procedures declared in let blocks sometimes because they make the flo=
w of control jump around on the page - first you have to read the body of t=
he let block, which is lower on the screen, and then jump back up to the fu=
nctions that were defined at the top of the block.

However, I think that inner functions make a lot of sense if you think =
of each top-level procedure like its own little module. If you think like t=
hat, then writing inner procedures means grouping related code together and=
making the overall structure more clear.

I've been looking over one of the soluti=
ons to a Guile 100 problem
(a basic version of the `ls' command) at the link below.=A0 It is
interesting stylistically because it works very hard at minimizing the
scope of procedures.=A0 It uses a lot of procedures within procedures,
like, for example, within a `let*' block.

Personally, I only define a procedure within a procedure if the
inner procedure is not a pure function, e.g. if its result
depends on information other than its parameters, and that
information only exists within the scope of the outer procedure.
I tend to keep most pure functions at the module level. But,
I'm not a very Schemey guy.

One could look at using lots of procedures within procedures as good
defensive programming style: hiding unnecessary functions.

Or one could look at it as being less clear because you end up with
longer "paragraphs" to read.

Do you have a personal philosophy on how much you try to minimize
the scope of procedures? =A0If you were writing a tutorial,
what would you say?
-Mike Gran

I'm glad that you've made a great pi=
ece of work to integrate guile with the rest of the world. I see you implem=
ed it using guile's hash tables and lists, which seems sound.

The problem lies within the way guile deals with hash tables. Actually, the=
re are several problems that need to be addressed:

- firstly, guile's hash tables are maps, not dictionaries,=
so they are insensitive to order. This behaviour is desired if we want to =
use them to represent sets or maps; however, PHP arrays, and -- as I presum=
e -- JavaScript objects -- store the information about the order of their e=
lements. Lisp-style sollution would be to store them as assoc lists, which =
in turn have linear access time.

- secondly, there is no default notation to=
create hash tables nor sets; using them forces

a programme=
r to drop homoiconicity, as their default print representation is #<hash=
-table 1c8a940 1/31> or something even uglier. I think that this is done=
properly in Clojure.

- thirdly, refering to hashes (as well as a=
ssoc lists, goops' object slots, vector/array elements) is truly cumber=
some. I once wrote a hash-read-extension that allowed to refer to hashes/ar=
rays/slots... using uniform notation #[object key], and to allow for nested=
references like #[ ... #[#[object key1] key2 ] ... ] using simpified notat=
ion #[object : key1 : key2 : ... ]. The implementation is rather inefficien=
t when it comes to performance, but makes coding much more efficient, and i=
t can be found here, if anyone's interested:

One could ask: why can't vectors, arrays, objects and =
hashes simply be applicable? (Of course, it is possible to implement applic=
able collections even now, but at a cost of loosing their print representat=
ion)

I think the issue with applicable goops obj=
ects emerged before, when someone wanted to implement python in guile, and =
wanted to provide a __call__ metod.

- lastly, guile's support for hash tables is limited -- there ain't=
even a built-in function that would return the size of a hash-table. My im=
plementation is inefficient (linear time), and it looks like this:

(define (hash-size hash-map)

=A0 (length (hash-va=
lues hash-map)))

Some time ago I saw here so=
meone who was using the print representation of a hash-table to read the nu=
mber of its elements, but it seems like a nasty hack, and it stopped workin=
g once the print representation changed.

Sorry if I was a little off topic :)

<=
div style>Be the avant-garde!

M.

=

--047d7bf19894ddfbf304d9855bab--
From MAILER-DAEMON Thu Apr 04 06:16:06 2013
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1UNhDB-0005lR-Qs
for mharc-guile-user@gnu.org; Thu, 04 Apr 2013 06:16:05 -0400
Received: from eggs.gnu.org ([208.118.235.92]:56600)
by lists.gnu.org with esmtp (Exim 4.71)
(envelope-from ) id 1UNhD6-0005d0-Pm
for guile-user@gnu.org; Thu, 04 Apr 2013 06:16:03 -0400
Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
(envelope-from ) id 1UNhCy-0007Mi-R6
for guile-user@gnu.org; Thu, 04 Apr 2013 06:16:00 -0400
Received: from mail-bk0-x22e.google.com ([2a00:1450:4008:c01::22e]:43364)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelope-from ) id 1UNhCy-0007MG-Il
for guile-user@gnu.org; Thu, 04 Apr 2013 06:15:52 -0400
Received: by mail-bk0-f46.google.com with SMTP id je9so1384417bkc.5
for ; Thu, 04 Apr 2013 03:15:51 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
h=x-received:from:to:cc:subject:references:date:in-reply-to
:message-id:user-agent:mime-version:content-type;
bh=Ev4KUmUczX+QZnWx2Z/4BZxXcNW+8Z4WhaR47FbgPP0=;
b=yNlzjcyt3Ac1oU83lfj9VwZgcGN622traztrYhBPlCtMgCBznkMuYws18fWPbfPhU2
6Oro60KlNAyBWzjLz8wuArR9AgtA7QC8MV627dXmSeugfFAA/AEfNV9UYTP9qnTm4Iwb
eMfuIvFJraZ+8KG12CcZKe6H7bGL7Rf9VYyZ1MwBQEvRWtIKj32IVBAwkNhGHGy+j/UC
n14IaKt1zQml1gE/cvFI/G5t+PzoykGl8wb/O6FCAFLnlLo4n/gQygsZOxEbh4zFaj9o
4EL38fjF1He4XLxPGy86gjrF+u1B/lvV7DUs2cNWMEaFWPMPFG/FPvSbe8MN8Lf8F6ee
/cTg==
X-Received: by 10.205.3.68 with SMTP id nx4mr3813305bkb.139.1365070550981;
Thu, 04 Apr 2013 03:15:50 -0700 (PDT)
Received: from taylan.dyndns.org (p4FD93BE3.dip.t-dialin.net. [79.217.59.227])
by mx.google.com with ESMTPS id
gu14sm5490832bkc.1.2013.04.04.03.15.48
(version=TLSv1.2 cipher=RC4-SHA bits=128/128);
Thu, 04 Apr 2013 03:15:49 -0700 (PDT)
From: taylanbayirli@gmail.com (Taylan Ulrich B.)
To: Panicz Maciej Godek
Subject: Re: guile-json 0.2.0 released
References:
Date: Thu, 04 Apr 2013 12:15:47 +0200
In-Reply-To:
(Panicz Maciej Godek's message of "Thu, 4 Apr 2013 11:11:41 +0200")
Message-ID: <871uaqha98.fsf@taylan.dyndns.org>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (berkeley-unix)
MIME-Version: 1.0
Content-Type: text/plain
X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address
(bad octet value).
X-Received-From: 2a00:1450:4008:c01::22e
Cc: guile-user
X-BeenThere: guile-user@gnu.org
X-Mailman-Version: 2.1.14
Precedence: list
List-Id: General Guile related discussions
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Thu, 04 Apr 2013 10:16:04 -0000
Panicz Maciej Godek writes:
> - firstly, guile's hash tables are maps, not dictionaries, so they are
> insensitive to order. This behaviour is desired if we want to use them
> to represent sets or maps; however, PHP arrays, and -- as I presume --
> JavaScript objects -- store the information about the order of their
> elements. Lisp-style sollution would be to store them as assoc lists,
> which in turn have linear access time.
>From json.org (which is official):
"An object is an unordered set of name/value pairs."
(Object means dictionary/map in JSON terminology.)
I think this is consistent with common expectations from a dictionary
data structure. At least in my experience. Should the ordering be
important, a supplementary key-vector (or list) could be used easily
enough in my opinion; bundling that functionality into hash-tables is
probably not worth it unless it is trivial to implement.
> - secondly, there is no default notation to create hash tables nor
> sets; using them forces
> a programmer to drop homoiconicity, as their default print
> representation is # or something even uglier.
> I think that this is done properly in Clojure.
That is not what homoiconicity means. There are more data types that
lack a proper external representation; most notably procedures. For
transmission of data, converting to an alist and back is probably good
enough; this can also be used as a "hack" for having "literal"
dictionaries in code: (alist->dictionary '(...))
So again, this is probably nothing that needs be implemented urgently.
> - thirdly, refering to hashes (as well as assoc lists, goops' object
> slots, vector/array elements) is truly cumbersome. I once wrote a
> hash-read-extension that allowed to refer to hashes/arrays/slots...
> using uniform notation #[object key], and to allow for nested
> references like #[ ... #[#[object key1] key2 ] ... ] using simpified
> notation #[object : key1 : key2 : ... ]. The implementation is rather
> inefficient when it comes to performance, but makes coding much more
> efficient, and it can be found here, if anyone's interested:
> https://bitbucket.org/panicz/slayer/src/33cf0116da95dea6928ab1011994569b5a5181ad/extra/ref.
> scm?at=goose-3d
> One could ask: why can't vectors, arrays, objects and hashes simply be
> applicable? (Of course, it is possible to implement applicable
> collections even now, but at a cost of loosing their print
> representation)
SRFI-105 is probably the preferable solution to this problem, since it's
an SRFI. Guile already supports it, but I don't know how many accessors
are built-in; it should be trivial to implement any you want though.
> - lastly, guile's support for hash tables is limited -- there ain't
> even a built-in function that would return the size of a hash-table.
> My implementation is inefficient (linear time), and it looks like
> this:
> (define (hash-size hash-map)
> (length (hash-values hash-map)))
I don't know how exactly hash-tables are implemented in Guile, but one
probably needs to walk through the whole structure to count the size;
then the most efficient simple implementation of `hash-size' is one
which walks through it only once:
(hash-fold (lambda (key value size) (1+ size)) 0 hash-table)
Other than that, the size could be kept in the internal representation
of the hash-table, but I'm not sure of the pay-offs.
Kind regards,
Taylan :)
From MAILER-DAEMON Thu Apr 04 08:07:04 2013
Received: from list by lists.gnu.org with archive (Exim 4.71)
id 1UNiwa-0007uZ-E0
for mharc-guile-user@gnu.org; Thu, 04 Apr 2013 08:07:04 -0400
Received: from eggs.gnu.org ([208.118.235.92]:35048)
by lists.gnu.org with esmtp (Exim 4.71)
(envelope-from ) id 1UNiwS-0007jS-PJ
for guile-user@gnu.org; Thu, 04 Apr 2013 08:07:02 -0400
Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)
(envelope-from ) id 1UNiwO-0006Zf-QZ
for guile-user@gnu.org; Thu, 04 Apr 2013 08:06:56 -0400
Received: from mail-wg0-f48.google.com ([74.125.82.48]:55646)
by eggs.gnu.org with esmtp (Exim 4.71)
(envelope-from ) id 1UNiwO-0006ZR-5u
for guile-user@gnu.org; Thu, 04 Apr 2013 08:06:52 -0400
Received: by mail-wg0-f48.google.com with SMTP id m15so2634373wgh.27
for ; Thu, 04 Apr 2013 05:06:51 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;
h=mime-version:x-received:in-reply-to:references:date:message-id
:subject:from:to:cc:content-type;
bh=0GMT1q6onJZGTm6J156JuOz6D5qXD2t4RcocT9wRba8=;
b=k9MeCwEFg9hZKHmXzwM6cwxnbmyLJ0hYmV5TH9xkL+Cn5NDKoo3fbmEwYDSTG3T2fv
KmHF/62vP9uLVhrDn1SdRWGGrayO6tgvERLBdem+IfaGl60fRSij1+AMwSJg+Dk5PhF5
b1Z7H+rBw8wQC30x32cpChi0rmEb1wFLaxQUb961YInUO2hr45MBRVfgVwUiPz397r77
HtwGXsvkam+pNUDspuQJ/sjkcxTv+R6Up1JC6qH40/x1MK/io9ovcU3K0Kc/ooWu9LAI
DJGOHnj6qi5/bmB6BfYxa/XOL7yh63l/feN6fKhAzq6RRm6fTgf26HVuHVcxHq+1r+YH
vNJA==
MIME-Version: 1.0
X-Received: by 10.180.87.97 with SMTP id w1mr3069675wiz.2.1365077210645; Thu,
04 Apr 2013 05:06:50 -0700 (PDT)
Received: by 10.194.60.100 with HTTP; Thu, 4 Apr 2013 05:06:50 -0700 (PDT)
In-Reply-To: <871uaqha98.fsf@taylan.dyndns.org>
References:
<871uaqha98.fsf@taylan.dyndns.org>
Date: Thu, 4 Apr 2013 14:06:50 +0200
Message-ID:
Subject: Re: guile-json 0.2.0 released
From: Panicz Maciej Godek
To: "Taylan Ulrich B."
Content-Type: multipart/alternative; boundary=f46d044402823b4acd04d987ce8a
X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy]
X-Received-From: 74.125.82.48
Cc: guile-user
X-BeenThere: guile-user@gnu.org
X-Mailman-Version: 2.1.14
Precedence: list
List-Id: General Guile related discussions
List-Unsubscribe: ,
List-Archive:
List-Post:
List-Help:
List-Subscribe: ,
X-List-Received-Date: Thu, 04 Apr 2013 12:07:03 -0000
--f46d044402823b4acd04d987ce8a
Content-Type: text/plain; charset=ISO-8859-1
2013/4/4 Taylan Ulrich B.
> Panicz Maciej Godek writes:
>
> > - firstly, guile's hash tables are maps, not dictionaries, so they are
> > insensitive to order. This behaviour is desired if we want to use them
> > to represent sets or maps; however, PHP arrays, and -- as I presume --
> > JavaScript objects -- store the information about the order of their
> > elements. Lisp-style sollution would be to store them as assoc lists,
> > which in turn have linear access time.
>
> From json.org (which is official):
> "An object is an unordered set of name/value pairs."
>
> (Object means dictionary/map in JSON terminology.)
>
> I think this is consistent with common expectations from a dictionary
> data structure. At least in my experience. Should the ordering be
> important, a supplementary key-vector (or list) could be used easily
> enough in my opinion; bundling that functionality into hash-tables is
> probably not worth it unless it is trivial to implement.
Well, I see why the representation based on hash tables is adequate for
JSON. There are, however, situations, when one wants to have an ordered
set, and it's good to have choice. Clojure, for instance, offers such
choice, and from the perspective of a programmer it's better to have a
choice.
> > - secondly, there is no default notation to create hash tables nor
> > sets; using them forces
> > a programmer to drop homoiconicity, as their default print
> > representation is # or something even uglier.
> > I think that this is done properly in Clojure.
>
> That is not what homoiconicity means. There are more data types that
> lack a proper external representation; most notably procedures. For
> transmission of data, converting to an alist and back is probably good
> enough; this can also be used as a "hack" for having "literal"
> dictionaries in code: (alist->dictionary '(...))
>
> Of course it can. However it's not convenient. I use emacs+geiser and when
I want to see the content of a variable -- if it's a list or some other
basic type -- I just point a cursor on it and I get the value in a
minibuffer. When I want to see the content of hash-table, I need to
explicitly evaluate (hash-map->list cons my-hash-table), which seems
unnecessary When a hash-table is nested, it turns into a nightmare. If
there was a more reader-friendly representation of hashes, it would be far
more convenient. I could come up with some representation myself, and use
it in my programs, but I guess that this problem is more serious and
requires more attention.
All in all, you don't write vector->list and list->vector to get a nice
printable representation of vectors -- there was an issue, and it has been
solved. Racket has its printable representation of hashes, which is much
nicer than the one of guile (although still not perfect).
So again, this is probably nothing that needs be implemented urgently.
Judging by the speed at which subsequent Reports on algorithmic language
Scheme are released, schemers don't seem know the word "urgent" :) Which is
good.
However, I think it is an important matter. I also think that it is no good
for scheme implementations to diverge from one another, if there is no good
reason for that.
Note that easy-to-use hash tables are what win the market for PHP, despite
many drawbacks of that language.
> - thirdly, refering to hashes (as well as assoc lists, goops' object
> > slots, vector/array elements) is truly cumbersome. I once wrote a
> > hash-read-extension that allowed to refer to hashes/arrays/slots...
> > using uniform notation #[object key], and to allow for nested
> > references like #[ ... #[#[object key1] key2 ] ... ] using simpified
> > notation #[object : key1 : key2 : ... ]. The implementation is rather
> > inefficient when it comes to performance, but makes coding much more
> > efficient, and it can be found here, if anyone's interested:
> >
> https://bitbucket.org/panicz/slayer/src/33cf0116da95dea6928ab1011994569b5a5181ad/extra/ref
> .
> > scm?at=goose-3d
> > One could ask: why can't vectors, arrays, objects and hashes simply be
> > applicable? (Of course, it is possible to implement applicable
> > collections even now, but at a cost of loosing their print
> > representation)
>
> SRFI-105 is probably the preferable solution to this problem, since it's
> an SRFI. Guile already supports it, but I don't know how many accessors
> are built-in; it should be trivial to implement any you want though.
>
> I know of no other implementation of Scheme than Guile which supports
SRFI-105. And I guess that the implementators will remain reluctant with
regard to it, as it introduces more randomness to the way the code can be
written.
On the other hand, what are the argumets against making hash-tables,
vectors et al. applicable, assuming that "programming languages should be
designed not by piling feature on top of feature, but by removing the
weaknesses and restrictions that make additional features appear necessary"?
> - lastly, guile's support for hash tables is limited -- there ain't
> > even a built-in function that would return the size of a hash-table.
> > My implementation is inefficient (linear time), and it looks like
> > this:
> > (define (hash-size hash-map)
> > (length (hash-values hash-map)))
>
> I don't know how exactly hash-tables are implemented in Guile, but one
> probably needs to walk through the whole structure to count the size;
> then the most efficient simple implementation of `hash-size' is one
> which walks through it only once:
>
> (hash-fold (lambda (key value size) (1+ size)) 0 hash-table)
>
> Other than that, the size could be kept in the internal representation
> of the hash-table, but I'm not sure of the pay-offs.
>
> Plainly, the size is kept in the internal representation of the hash table:
typedef struct scm_t_hashtable {
unsigned long n_items; /* number of items in table */
...
cf.
http://git.savannah.gnu.org/gitweb/?p=guile.git;a=blob;f=libguile/hashtab.h;h=82ed22e66eb1f5045793cfc55cca0be040d4aab1;hb=HEAD#l66
It would be really cheap&easy to get it from there. I just wanted to show
that hash-tables are neglected in Scheme in general, and in Guile in
particular.
Best regards!
M.
--f46d044402823b4acd04d987ce8a
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

> - firstly, guile's hash tables are maps, not dictionaries, so they=
are
> insensitive to order. This behaviour is desired if we want to use them=
> to represent sets or maps; however, PHP arrays, and -- as I presume --=
> JavaScript objects -- store the information about the order of their
> elements. Lisp-style sollution would be to store them as assoc lists,<=
br>
> which in turn have linear access time.

From json.org (whic=
h is official):
"An object is an unordered set of name/value pairs."

(Object means dictionary/map in JSON terminology.)

I think this is consistent with common expectations from a dictionary
data structure. =A0At least in my experience. =A0Should the ordering be
important, a supplementary key-vector (or list) could be used easily
enough in my opinion; bundling that functionality into hash-tables is
probably not worth it unless it is trivial to implement.

<=
br>

Well, I see why the representation based on hash tables=
is adequate for JSON. There are, however, situations, when one wants to ha=
ve an ordered set, and it's good to have choice. Clojure, for instance,=
offers such choice, and from the perspective of a programmer it's bett=
er to have a choice.

=A0

> - secondly, there is no default notation to create hash tables nor
> sets; using them forces
> a programmer to drop homoiconicity, as their default print
> representation is #<hash-table 1c8a940 1/31> or something even u=
glier.
> I think that this is done properly in Clojure.

That is not what homoiconicity means. =A0There are more data types th=
at
lack a proper external representation; most notably procedures. =A0For
transmission of data, converting to an alist and back is probably good
enough; this can also be used as a "hack" for having "litera=
l"
dictionaries in code: (alist->dictionary '(...))

Of course it can. However it's not convenie=
nt. I use emacs+geiser and when I want to see the content of a variable -- =
if it's a list or some other basic type -- I just point a cursor on it =
and I get the value in a minibuffer. When I want to see the content of hash=
-table, I need to explicitly evaluate (hash-map->list cons my-hash-table=
), which seems unnecessary When a hash-table is nested, it turns into a nig=
htmare. If there was a more reader-friendly representation of hashes, it wo=
uld be far more convenient. I could come up with some representation myself=
, and use it in my programs, but I guess that this problem is more serious =
and requires more attention.

All in all, you don't write vector->=
list and list->vector to get a nice printable representation of vectors =
-- there was an issue, and it has been solved. Racket has its printable rep=
resentation of hashes, which is much nicer than the one of guile (although =
still not perfect).

So again, this is probably nothing that needs be implemented urgently.

=A0

Judging by the speed at which subsequent R=
eports on algorithmic language Scheme are released, schemers don't seem=
know the word "urgent" :) Which is good.

However, I think it is an important matter. I also think that it=
is no good for scheme implementations to diverge from one another, if ther=
e is no good reason for that.

=A0

Note that easy-=
to-use hash tables are what win the market for PHP, despite many drawbacks =
of that language.

> - thirdly, refering to hashes (as well as assoc lists, goops' obje=
ct
> slots, vector/array elements) is truly cumbersome. I once wrote a
> hash-read-extension that allowed to refer to hashes/arrays/slots...
> using uniform notation #[object key], and to allow for nested
> references like #[ ... #[#[object key1] key2 ] ... ] using simpified
> notation #[object : key1 : key2 : ... ]. The implementation is rather<=
br>
> inefficient when it comes to performance, but makes coding much more
> efficient, and it can be found here, if anyone's interested:
> https://bitbucket.org/pa=
nicz/slayer/src/33cf0116da95dea6928ab1011994569b5a5181ad/extra/ref.
> scm?at=3Dgoose-3d
> One could ask: why can't vectors, arrays, objects and hashes simpl=
y be
> applicable? (Of course, it is possible to implement applicable
> collections even now, but at a cost of loosing their print
> representation)

SRFI-105 is probably the preferable solution to this problem, since i=
t's
an SRFI. =A0Guile already supports it, but I don't know how many access=
ors
are built-in; it should be trivial to implement any you want though.

I know of no other impl=
ementation of Scheme than Guile which supports SRFI-105. And I guess that t=
he implementators will remain reluctant with regard to it, as it introduces=
more randomness to the way the code can be written.

On the other hand, what are the argumets against making hash-tab=
les, vectors et al. applicable, assuming that "programming languages should be designed not by pil=
ing feature on top of feature, but by removing the weaknesses and restricti=
ons that make additional features appear necessary"?

> - lastly, guile's support for hash tables is limited -- there ain&=
#39;t
> even a built-in function that would return the size of a hash-table.
> My implementation is inefficient (linear time), and it looks like
> this:
> (define (hash-size hash-map)
> (length (hash-values hash-map)))

I don't know how exactly hash-tables are implemented in Guile, bu=
t one
probably needs to walk through the whole structure to count the size;
then the most efficient simple implementation of `hash-size' is one
which walks through it only once:

(hash-fold (lambda (key value size) (1+ size)) 0 hash-table)

Other than that, the size could be kept in the internal representation
of the hash-table, but I'm not sure of the pay-offs.

Plainly, the size is kept in the internal representation of th=
e hash table: