From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: Goswin von Brederlow <goswin-v-b@web.de>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] A shallow option type
Date: Mon, 7 May 2012 09:29:11 +0900 [thread overview]
Message-ID: <345FFB0F-E4E0-43C5-864E-625E7AAAF940@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <87aa1lcohv.fsf@frosties.localnet>
On 2012/05/07, at 0:34, Goswin von Brederlow wrote:
> Jacques Garrigue <garrigue@math.nagoya-u.ac.jp> writes:
>
>> Hi Goswin,
>>
>> Actually I remember discussing this issue with Xavier Leroy a long time ago,
>> and we ended up concluding that this could be done in a clean way by using
>> a bit pattern not yet used for ocaml values.
>>
>> Our idea was that rather than put some restriction on the shallowness of
>> types (which is very hard to implement), one should just allow arbitrary nesting
>> of option types, and represent the sequence "Some (Some (... ( Some None) ...))"
>> as an integer.
>> I think I even tried an implementation, but we then concluded that there
>> was not enough demand to put it in the compiler.
>
> The advantage of providing it by the compiler would be to allow pattern
> matching.
And also being compatible with the default option type, and proper marshaling support.
It's really a cost vs. usefulness discussion.
I see no good solution for marshaling.
It would be nice to be able to add hooks to the marshaler for handling
pointers outside of the value area...
>> However there is nothing wrong with providing it as a library.
>> The basic idea is that you have only two kinds of values in ocaml:
>> integers, which have their lower bit to 1, and pointers, which must
>> all be multiples of 4 (on 32-bit architectures).
>> So the pattern (v % 4) == 2 is not used.
>
> Actualy isn't (v % 4) == 2 an exception?
>
> caml/callback.h:
> #define Make_exception_result(v) ((v) | 2)
> #define Is_exception_result(v) (((v) & 3) == 2)
> #define Extract_exception(v) ((v) & ~3)
>
> So returning an Sopt.none in a callback would be taken as exception. :)
Well-spotted.
It seems that this use of the second bit was added after our discussion.
But the fundamental idea is just to represent "Some (Some (... ( Some None) ...))"
by a special collection of pointers, and this can be done in other ways,
like allocating a region in the C heap, or using a non-allocatable region (you only
need to now that these pointers will never be used).
Here is a version using Bigarray to allocate such a protected region:
module Sopt : sig
type +'a t
val none : 'a t
val some : 'a -> 'a t
val is_none : 'a t -> bool
val arg : 'a t -> 'a
val is_sopt : 'a t -> bool
val depth : 'a t -> int
end = struct
type 'a t = int
let area = Bigarray.(Array1.create int32 c_layout 1024)
let none : int = Obj.obj (Obj.field (Obj.repr area) 1)
let is_none x = (x = none)
let is_sopt x = (x >= none) && (x < none + 2048)
let some (x : 'a) : 'a t =
let y : 'a t = Obj.magic x in
if is_sopt y then
if y = none + 2047 then invalid_arg "Sopt.some" else y + 2
else y
let arg (x : 'a t) : 'a =
if is_sopt x then
if is_none x then invalid_arg "Sopt.arg" else Obj.magic (x-2)
else Obj.magic x
let depth x =
if is_sopt x then ((x - none) lor 1) lsr 1 else -1
end
> The implementation relies on specific aspect of the compiler to
> construct those values. I would give it a 99% chance to fail with an
> llvm backend for ocaml for example. Using C stubs that directly
> manipulate the bits seems a better approach.
>
> For example nothing says x + 2 can't be implemented as
>
> value add(value x, value y) {
> return (x & ~1) + y;
> }
>
> as opposed to
>
> value add(value x, value y) {
> return x + y - 1;
> }
Actually I'm confident that any backend using a data representation compatible
with ocaml is going to implement addition the same way.
There are two reasons:
* most processors can add two registers and a small constant in one operation
* there is no reason to depart from the already published approach
But of course there is nothing wrong to writing those as C primitives if you
are already writing stubs. You might just want to add the "noalloc" qualifier
to make calling them more efficient.
Jacques
next prev parent reply other threads:[~2012-05-07 0:29 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-05-05 13:33 Goswin von Brederlow
2012-05-05 13:50 ` Gabriel Scherer
2012-05-05 14:48 ` Andreas Rossberg
2012-05-05 15:07 ` Andreas Rossberg
2012-05-05 16:22 ` Goswin von Brederlow
2012-05-05 17:11 ` Gabriel Scherer
2012-05-06 10:12 ` Goswin von Brederlow
2012-05-06 10:20 ` Goswin von Brederlow
2012-05-06 13:01 ` Jacques Garrigue
2012-05-06 15:34 ` Goswin von Brederlow
2012-05-07 0:29 ` Jacques Garrigue [this message]
2012-05-07 1:27 ` Jacques Garrigue
2012-05-07 2:34 ` Jacques Garrigue
2012-05-07 8:11 ` Jacques Garrigue
2012-05-07 17:07 ` Goswin von Brederlow
2012-05-08 0:07 ` Jacques Garrigue
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=345FFB0F-E4E0-43C5-864E-625E7AAAF940@math.nagoya-u.ac.jp \
--to=garrigue@math.nagoya-u.ac.jp \
--cc=caml-list@inria.fr \
--cc=goswin-v-b@web.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox