caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Goswin von Brederlow <goswin-v-b@web.de>
To: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
Cc: Goswin von Brederlow <goswin-v-b@web.de>,
	OCaML List Mailing <caml-list@inria.fr>
Subject: Re: [Caml-list] A shallow option type
Date: Mon, 07 May 2012 19:07:39 +0200	[thread overview]
Message-ID: <87397bly1w.fsf@frosties.localnet> (raw)
In-Reply-To: <D350BA18-9214-47C7-8921-4D4AFD4DE356@math.nagoya-u.ac.jp> (Jacques Garrigue's message of "Mon, 7 May 2012 17:11:04 +0900")

Jacques Garrigue <garrigue@math.nagoya-u.ac.jp> writes:

> Sorry for all these mails.
> Looks like I don't think well when I'm sleepy...
>
> Anyway, I think that at last I have a reasonable (much simpler) solution.
> This still uses sopt_tag (i.e. lazy_tag-1), but this time the argument is
> the number of "some" constructors, so there is no extra cost for marshaling.
> The only values on which Sopt.some is not the identity are those with a
> single argument, which is additionally represented by an integer between 0 and last.
> Moreover, even if for some reason you build such a value using a real sum
> type, you still have Sopt.arg (Sopt.some v) = v, the only change being a loss
> of sharing (which is anyway not guaranteed by the ocaml specification).
>
> Jacques
>
> 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 depth : 'a t -> int
> end = struct
>  type 'a t = Obj.t
>  let sopt_tag = Obj.lazy_tag - 1
>  let none = Obj.new_block sopt_tag 1
>  let last = 255
>  let area = Array.create (last+1) none
>  let () =
>    Obj.set_field none 0 (Obj.repr 0);
>    for i = 1 to last do
>      let stub = Obj.new_block sopt_tag 1 in
>      Obj.set_field stub 0 (Obj.repr i);
>      area.(i) <- stub
>    done
>  let is_none x = (x = none)
>  let is_sopt x =
>    Obj.is_block x && Obj.tag x = sopt_tag && Obj.size x = 1 &&
>    let i = Obj.obj (Obj.field x 0) in i >= 0 && i <= last
>  let depth x =
>    let x = Obj.repr x in
>    if is_sopt x then Obj.obj (Obj.field x 0) else -1
>  let some (x : 'a) : 'a t =
>    let i = depth x in
>    if i < 0 then Obj.magic x else
>    if i = last then invalid_arg "Sopt.some" else Obj.obj area.(i+1)
>  let arg (x : 'a t) : 'a =
>    let i = depth x in
>    if i < 0 then Obj.magic x else
>    if i = 0 then invalid_arg "Sopt.arg" else Obj.obj area.(i-1)
> end

What exactly is the point of specially tagged blocks? All you need is a
bunch of pointers to values to encode the depth. You can use the value
pointed at to encode the index the pointer is at and physical equality
to ensure it actualy is one of your pointers:

let area = Array.init (last+1) (fun i -> ref i)

let is_sopt x =
  let r = Obj.repr x in
  Obj.is_block r && Obj.size x = 1 && Obj.is_int (Obj.field r 0) &&
  let i = Obj.obj (Obj.field r 0) in
  i >= 0 && i <= last && Obj.obj r == area.(i)

# is_sopt 1;;
- : bool = false
# is_sopt area.(5);;
- : bool = true
# is_sopt (ref 5);;
- : bool = false

MfG
        Goswin

  reply	other threads:[~2012-05-07 17:07 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
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 [this message]
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=87397bly1w.fsf@frosties.localnet \
    --to=goswin-v-b@web.de \
    --cc=caml-list@inria.fr \
    --cc=garrigue@math.nagoya-u.ac.jp \
    /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;
as well as URLs for NNTP newsgroup(s).