Re: [rust-dev] Dynamic in Rust

2013-08-25 Thread Sebastian Sylvan
On Sat, Aug 24, 2013 at 9:50 PM, Lindsey Kuper lind...@composition.alwrote:

 On Fri, Aug 23, 2013 at 8:30 PM, Sebastian Sylvan
 sebastian.syl...@gmail.com wrote:
  I'm sure you've all seen it, but C# has something similar but a lot more
  powerful. Basically, it has support for allowing runtime resolution of
 types
  if they are declared as having the dynamic type. But it's even better,
 the
  specification for how that resolution happens is defined in a library.
 This
  way you can work directly with dynamic values without having to cast them
  first (e.g. imagine just dotting your way through a JSON document and
  parse it on-demand).

 A more recent approach to this kind of thing is F# type providers
 (http://msdn.microsoft.com/en-us/library/hh156509.aspx and, for
 instance, http://fsharp.github.io/FSharp.Data/library/JsonProvider.html).
  Although I'm not especially familiar with them, they seem relevant
 and interesting.



I think they're partially non-overlapping approaches. Type providers is
about providing static types to dynamic data. I.e. someone has to write
down a schema. C# dynamic is about just dealing with dynamic data on the
fly. E.g. you could just open up any old JSON doc and start accessing
members. The two approaches are probably used for the same thing, much of
the time, but there are occasions where you can't define a static type for
something, so having an approach where you can do the runtime checks in a
less verbose fashion is nice (which I don't think the F# type providers
thing does).


-- 
Sebastian Sylvan
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-24 Thread Armin Ronacher

Hi,

On 24/08/2013 01:30, Sebastian Sylvan wrote:

I'm sure you've all seen it, but C# has something similar but a lot more
powerful.
Dynamic in C# is beautiful.  It's an amazing way to work with externally 
controlled data like JSON that is without equivalent in a strongly typed 
language currently.


I'm not sure how much of that Rust can reproduce, but if there is any 
way it has a strong +1 from me.



Regards,
Armin

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-24 Thread Lindsey Kuper
On Fri, Aug 23, 2013 at 8:30 PM, Sebastian Sylvan
sebastian.syl...@gmail.com wrote:
 I'm sure you've all seen it, but C# has something similar but a lot more
 powerful. Basically, it has support for allowing runtime resolution of types
 if they are declared as having the dynamic type. But it's even better, the
 specification for how that resolution happens is defined in a library. This
 way you can work directly with dynamic values without having to cast them
 first (e.g. imagine just dotting your way through a JSON document and
 parse it on-demand).

A more recent approach to this kind of thing is F# type providers
(http://msdn.microsoft.com/en-us/library/hh156509.aspx and, for
instance, http://fsharp.github.io/FSharp.Data/library/JsonProvider.html).
 Although I'm not especially familiar with them, they seem relevant
and interesting.

Lindsey
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Oren Ben-Kiki
Yes, this would be similar to the `Typeable` type class in Haskell. It
queries the vtable-equivalent, which contains stuff like the name of the
type and allows doing `typeof(x)`, dynamic casts, etc. This is heavily
magical (that is, depends on the hidden internal representation) and
properly belongs in the standard platform and not in a user-level library.


On Fri, Aug 23, 2013 at 4:40 PM, Niko Matsakis n...@alum.mit.edu wrote:

 Currently, this is not directly supported, though downcasting in
 general is something we have contemplated as a feature.  It might be
 possible to create some kind of horrible hack based on objects. A
 trait like:

 trait Dynamic { }
 implT Dynamic for T { }

 would allow any value to be cast to an object. The type descriptor can
 then be extracted from the vtable of the object using some rather
 fragile unsafe code that will doubtless break when we change the
 vtable format. The real question is what you can do with the type
 descriptor; they are not canonicalized, after all. Still, it's
 ... very close.  This is basically how dynamic downcasting would work,
 in any case.


 Niko

 On Fri, Aug 23, 2013 at 07:49:57AM +0300, Oren Ben-Kiki wrote:
  Is it possible to implement something like Haskell's Dynamic value holder
  in Rust? (This would be similar to supporting C++'s dynamic_cast).
  Basically, something like this:
 
  pub struct Dynamic { ... }
  impl Dynamic {
  pub fn put(value: ~T) { ... }
  pub fn get() - OptionT { ... }
  }
 
  I guess this would require unsafe code... even so, it seems to me that
 Rust
  pointers don't carry sufficient meta-data for the above to work. A
 possible
  workaround would be something like:
 
  pub struct Dynamic { type_name: ~str, ... }
  impl Dynamic {
  pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
  type_name, ... } }
  pub fn get('a self, type_name: str) - Option'a T {
  assert_eq!(type_name, self.type_name); ... } }
  }
 
  And placing the burden on the caller to always use the type name int
 when
  putting or getting `int` values, etc. This would still require some sort
 of
  unsafe code to cast the `~T` pointer into something and back, while
  ensuring that the storage for the `T` (whatever its size is) is not
  released until the `Dynamic` itself is.
 
  (Why do I need such a monstrosity? Well, I need it to define a
  `Configuration` container, which holds key/value pairs where whoever
 sets a
  value knows its type, whoever gets the value should ask for the same
 type,
  and the configuration can hold values of any type - not from a
 predefined
  list of types).
 
  Is such a thing possible, and if so, how?
 
  Thanks,
 
  Oren Ben-Kiki

  ___
  Rust-dev mailing list
  Rust-dev@mozilla.org
  https://mail.mozilla.org/listinfo/rust-dev


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Matthieu Monrocq
One question:

Do you only want to retrieve the exact type that was passed in, or would
you want to be able to extract an impl that matches the type actually
contained ?

The latter is more difficult to implement (dynamic_cast goes through hoops
to check those things), but it is doable if sufficient information is
encoded in the v-table.


On Fri, Aug 23, 2013 at 5:04 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Yes, this would be similar to the `Typeable` type class in Haskell. It
 queries the vtable-equivalent, which contains stuff like the name of the
 type and allows doing `typeof(x)`, dynamic casts, etc. This is heavily
 magical (that is, depends on the hidden internal representation) and
 properly belongs in the standard platform and not in a user-level library.


 On Fri, Aug 23, 2013 at 4:40 PM, Niko Matsakis n...@alum.mit.edu wrote:

 Currently, this is not directly supported, though downcasting in
 general is something we have contemplated as a feature.  It might be
 possible to create some kind of horrible hack based on objects. A
 trait like:

 trait Dynamic { }
 implT Dynamic for T { }

 would allow any value to be cast to an object. The type descriptor can
 then be extracted from the vtable of the object using some rather
 fragile unsafe code that will doubtless break when we change the
 vtable format. The real question is what you can do with the type
 descriptor; they are not canonicalized, after all. Still, it's
 ... very close.  This is basically how dynamic downcasting would work,
 in any case.


 Niko

 On Fri, Aug 23, 2013 at 07:49:57AM +0300, Oren Ben-Kiki wrote:
  Is it possible to implement something like Haskell's Dynamic value
 holder
  in Rust? (This would be similar to supporting C++'s dynamic_cast).
  Basically, something like this:
 
  pub struct Dynamic { ... }
  impl Dynamic {
  pub fn put(value: ~T) { ... }
  pub fn get() - OptionT { ... }
  }
 
  I guess this would require unsafe code... even so, it seems to me that
 Rust
  pointers don't carry sufficient meta-data for the above to work. A
 possible
  workaround would be something like:
 
  pub struct Dynamic { type_name: ~str, ... }
  impl Dynamic {
  pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
  type_name, ... } }
  pub fn get('a self, type_name: str) - Option'a T {
  assert_eq!(type_name, self.type_name); ... } }
  }
 
  And placing the burden on the caller to always use the type name int
 when
  putting or getting `int` values, etc. This would still require some
 sort of
  unsafe code to cast the `~T` pointer into something and back, while
  ensuring that the storage for the `T` (whatever its size is) is not
  released until the `Dynamic` itself is.
 
  (Why do I need such a monstrosity? Well, I need it to define a
  `Configuration` container, which holds key/value pairs where whoever
 sets a
  value knows its type, whoever gets the value should ask for the same
 type,
  and the configuration can hold values of any type - not from a
 predefined
  list of types).
 
  Is such a thing possible, and if so, how?
 
  Thanks,
 
  Oren Ben-Kiki

  ___
  Rust-dev mailing list
  Rust-dev@mozilla.org
  https://mail.mozilla.org/listinfo/rust-dev



 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Oren Ben-Kiki
That's a really good question. In my specific case, I need the exact same
type. But a proper implementation would presumably be able to provide
any matching type (I believe the Haskell implementation does this).


On Fri, Aug 23, 2013 at 7:17 PM, Matthieu Monrocq 
matthieu.monr...@gmail.com wrote:

 One question:

 Do you only want to retrieve the exact type that was passed in, or would
 you want to be able to extract an impl that matches the type actually
 contained ?

 The latter is more difficult to implement (dynamic_cast goes through hoops
 to check those things), but it is doable if sufficient information is
 encoded in the v-table.


 On Fri, Aug 23, 2013 at 5:04 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Yes, this would be similar to the `Typeable` type class in Haskell. It
 queries the vtable-equivalent, which contains stuff like the name of the
 type and allows doing `typeof(x)`, dynamic casts, etc. This is heavily
 magical (that is, depends on the hidden internal representation) and
 properly belongs in the standard platform and not in a user-level library.


 On Fri, Aug 23, 2013 at 4:40 PM, Niko Matsakis n...@alum.mit.edu wrote:

 Currently, this is not directly supported, though downcasting in
 general is something we have contemplated as a feature.  It might be
 possible to create some kind of horrible hack based on objects. A
 trait like:

 trait Dynamic { }
 implT Dynamic for T { }

 would allow any value to be cast to an object. The type descriptor can
 then be extracted from the vtable of the object using some rather
 fragile unsafe code that will doubtless break when we change the
 vtable format. The real question is what you can do with the type
 descriptor; they are not canonicalized, after all. Still, it's
 ... very close.  This is basically how dynamic downcasting would work,
 in any case.


 Niko

 On Fri, Aug 23, 2013 at 07:49:57AM +0300, Oren Ben-Kiki wrote:
  Is it possible to implement something like Haskell's Dynamic value
 holder
  in Rust? (This would be similar to supporting C++'s dynamic_cast).
  Basically, something like this:
 
  pub struct Dynamic { ... }
  impl Dynamic {
  pub fn put(value: ~T) { ... }
  pub fn get() - OptionT { ... }
  }
 
  I guess this would require unsafe code... even so, it seems to me that
 Rust
  pointers don't carry sufficient meta-data for the above to work. A
 possible
  workaround would be something like:
 
  pub struct Dynamic { type_name: ~str, ... }
  impl Dynamic {
  pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
  type_name, ... } }
  pub fn get('a self, type_name: str) - Option'a T {
  assert_eq!(type_name, self.type_name); ... } }
  }
 
  And placing the burden on the caller to always use the type name int
 when
  putting or getting `int` values, etc. This would still require some
 sort of
  unsafe code to cast the `~T` pointer into something and back, while
  ensuring that the storage for the `T` (whatever its size is) is not
  released until the `Dynamic` itself is.
 
  (Why do I need such a monstrosity? Well, I need it to define a
  `Configuration` container, which holds key/value pairs where whoever
 sets a
  value knows its type, whoever gets the value should ask for the same
 type,
  and the configuration can hold values of any type - not from a
 predefined
  list of types).
 
  Is such a thing possible, and if so, how?
 
  Thanks,
 
  Oren Ben-Kiki

  ___
  Rust-dev mailing list
  Rust-dev@mozilla.org
  https://mail.mozilla.org/listinfo/rust-dev



 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev



___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Patrick Walton

On 8/23/13 8:04 AM, Oren Ben-Kiki wrote:

Yes, this would be similar to the `Typeable` type class in Haskell. It
queries the vtable-equivalent, which contains stuff like the name of the
type and allows doing `typeof(x)`, dynamic casts, etc. This is heavily
magical (that is, depends on the hidden internal representation) and
properly belongs in the standard platform and not in a user-level library.


I had always figured we'd copy Haskell's `Data.Typeable` solution more 
or less exactly. I think we can do it in a library though, as Niko 
pointed out; in general we aren't afraid of adding deep 
compiler-specific magic into our libraries.


Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Oren Ben-Kiki
Yes, Rust has a `deriving` attribute one can attach to types (for stuff
like `Eq`, `Ord`, etc.).

That said, as long as the vtable is already there, I think Rust should do
what Haskell is moving to (automatically `derive Typeable`) - that is,
automatically place the necessary data in the vtable.

Haskell does place a restriction on _using_ the data, though. One must
explicitly request the type T has the trait `Typeable` in order to invoke
functionality that uses the data. Even though all types implement this
trait, this explicitly warns the caller that this function may do strange
things. I'm not sure what the right choice would be in Rust here.


On Fri, Aug 23, 2013 at 7:44 PM, Danny Gratzer danny.grat...@gmail.comwrote:

 I guess it's worth pointing out GHC's -XDeriveDataTypeable language
 extension, this let's the compiler automatically derive the Typeable
 instance for user defined datatypes. If you want to copy Data.Typeable
 having something (a macro?) to automagically implemented Typeable goes a
 long way to aiding usability.

 I'm not sure if an equivalent to Haskell's `derive` exists in Rust. I'm
 rather new here :)


 Cheers,
 Danny Gratzer


 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Patrick Walton

On 8/23/13 9:44 AM, Danny Gratzer wrote:

I guess it's worth pointing out GHC's -XDeriveDataTypeable language
extension, this let's the compiler automatically derive the Typeable
instance for user defined datatypes. If you want to copy Data.Typeable
having something (a macro?) to automagically implemented Typeable goes a
long way to aiding usability.

I'm not sure if an equivalent to Haskell's `derive` exists in Rust. I'm
rather new here :)


Yes, it's called #[deriving] and is a syntax extension. I was assuming 
that we'd implement it for `Typeable`.


Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Graydon Hoare
On 13-08-23 09:49 AM, Oren Ben-Kiki wrote:
 Yes, Rust has a `deriving` attribute one can attach to types (for stuff
 like `Eq`, `Ord`, etc.).
 
 That said, as long as the vtable is already there, I think Rust should
 do what Haskell is moving to (automatically `derive Typeable`) - that
 is, automatically place the necessary data in the vtable.

Every type descriptor has a visitor-glue method written into it, which
provides typeable-like structural reflection (std::reflect) on types,
but not (presently) efficient type-equality. We'd need to augment it
slightly to provide that, but I think it'd be possible. This code is
used in fmt! for example to support printing arbitrary values (std::repr).

-Graydon

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Oren Ben-Kiki
Interesting - I see std::intrinsics::unstable::get_tydescrT - *TyDescr...

Two questions:

- Can this be used for a quick type equality check (same pointer = same
type)?

- How can one invoke `get_tydescrint()` or `get_tydescrT` (when `T` is
a type parameter of the current function)? I get a syntax error on the
`int` or `T`.


On Fri, Aug 23, 2013 at 8:50 PM, Graydon Hoare gray...@mozilla.com wrote:

 On 13-08-23 09:49 AM, Oren Ben-Kiki wrote:
  Yes, Rust has a `deriving` attribute one can attach to types (for stuff
  like `Eq`, `Ord`, etc.).
 
  That said, as long as the vtable is already there, I think Rust should
  do what Haskell is moving to (automatically `derive Typeable`) - that
  is, automatically place the necessary data in the vtable.

 Every type descriptor has a visitor-glue method written into it, which
 provides typeable-like structural reflection (std::reflect) on types,
 but not (presently) efficient type-equality. We'd need to augment it
 slightly to provide that, but I think it'd be possible. This code is
 used in fmt! for example to support printing arbitrary values (std::repr).

 -Graydon


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Graydon Hoare
On 13-08-23 11:08 AM, Oren Ben-Kiki wrote:
 Interesting - I see std::intrinsics::unstable::get_tydescrT - *TyDescr...
 
 Two questions:
 
 - Can this be used for a quick type equality check (same pointer =
 same type)?

No, as I said, it does not support efficient type-equality. We don't
normalize all types. You should be able to count on one-way equality at
the moment (same pointer = same type) but not vice-versa.

 - How can one invoke `get_tydescrint()` or `get_tydescrT` (when `T`
 is a type parameter of the current function)? I get a syntax error on
 the `int` or `T`. 

get_tydesc::T(). This is the foo vs foo:: syntax papercut. Gets
everyone, sorry. It's the price of using  for type parameters rather
than []. We need a better error message for it.

-Graydon

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Patrick Walton

On 8/23/13 11:15 AM, Graydon Hoare wrote:

get_tydesc::T(). This is the foo vs foo:: syntax papercut. Gets
everyone, sorry. It's the price of using  for type parameters rather
than []. We need a better error message for it.


Actually, [] would have the same problem, because of array indexing.

Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Oren Ben-Kiki
Got it, thanks. I guess that the TyDescr could be extended in the future to
support type equality and other things. In the meanwhile, in my case I'll
have the user manually annotate the Dynamic with an (interned) string
containing the type name, and pray people don't mess it up.

Thanks!


On Fri, Aug 23, 2013 at 9:15 PM, Graydon Hoare gray...@mozilla.com wrote:

 On 13-08-23 11:08 AM, Oren Ben-Kiki wrote:
  Interesting - I see std::intrinsics::unstable::get_tydescrT -
 *TyDescr...
 
  Two questions:
 
  - Can this be used for a quick type equality check (same pointer =
  same type)?

 No, as I said, it does not support efficient type-equality. We don't
 normalize all types. You should be able to count on one-way equality at
 the moment (same pointer = same type) but not vice-versa.

  - How can one invoke `get_tydescrint()` or `get_tydescrT` (when `T`
  is a type parameter of the current function)? I get a syntax error on
  the `int` or `T`.

 get_tydesc::T(). This is the foo vs foo:: syntax papercut. Gets
 everyone, sorry. It's the price of using  for type parameters rather
 than []. We need a better error message for it.

 -Graydon


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Graydon Hoare
On 13-08-23 11:16 AM, Patrick Walton wrote:
 On 8/23/13 11:15 AM, Graydon Hoare wrote:
 get_tydesc::T(). This is the foo vs foo:: syntax papercut. Gets
 everyone, sorry. It's the price of using  for type parameters rather
 than []. We need a better error message for it.
 
 Actually, [] would have the same problem, because of array indexing.

Naturally, which is why array indexing (way back when) was foo.(index).
But it was a throwaway comment; this is all very much water under the
bridge, not in any way suggesting we revisit.

-Graydon

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Michael Sullivan
So, as it turns out, something closely related can be implemented in
completely safe rust.

(The ideas here are based on http://mlton.org/UniversalType and the
presentation of extensible types from my undergrad PL class. The
implementation is based on the mlton UniversalType page, but I change the
interface to be more like extensible types. If anybody cares, SML code for
this is https://gist.github.com/msullivan/6324908.)

We can implement a universal type that values of any (cloneable, not
containing borrowed pointers) type can be injected to. The catch is that
the values aren't actually keyed by the type, but by tags that are
generated at runtime. This is sometimes useful (you can distinguish between
different classes of values of the same type) and sometimes annoying (you
have to manage the tags).

The implementation here is pretty clever, but also kind of silly. It would
probably actually be better in practice to do something unsafe internally
with dynamically generated tag values.

mod ClosureUniversal {
// A value of universal type is a pair of functions.  store will
// write the underlying value into the associated tag, while clear
// will erase the data in the tag to prevent space leaks.
pub struct Univ {
priv store: @fn(),
priv clear: @fn()
}

// A tag is a mutable option used as a scratch space to write
// into when inspecting a tag.
pub struct TagA {
priv r: @mut OptionA
}

pub fn new_tagA:'static() - TagA {
Tag { r: @mut None }
}

pub fn injectA:Clone+'static(tag: TagA, x: A) - Univ {
Univ {
store: || *tag.r = Some(x.clone()),
clear: || *tag.r = None
}
}

pub fn projectA:Clone+'static(tag: TagA, x: Univ) - OptionA {
// Cause the value to be written into its tag. If the universal
// value was injected with our tag, then it will be in tag.r.
(x.store)();
// Read out the value.
let res = (*tag.r).clone();
// Clear the value, to prevent space leaks.
(x.clear)();
res
}
}


fn main() {
use ClosureUniversal::*;

// Create some tags
let int_tag = new_tag::int();
let str_tag = new_tag::~str();

// Create some universal values with those tags
let u1 = inject(int_tag, 5);
let u2 = inject(int_tag, 6);
let u3 = inject(str_tag, ~hello, world);

// Try reading them
println(fmt!(%?, project(int_tag, u1))); // Some(5)
println(fmt!(%?, project(int_tag, u2))); // Some(6)
println(fmt!(%?, project(int_tag, u3))); // None

println(fmt!(%?, project(str_tag, u1))); // None
println(fmt!(%?, project(str_tag, u2))); // None
println(fmt!(%?, project(str_tag, u3))); // Some(~hello, world)

// Try out a *different* int tag.
let int_tag2 = new_tag::int();
// It can not be used to read things created by the other int tag
println(fmt!(%?, project(int_tag2, u1))); // None
}

(Code is also up at https://gist.github.com/msullivan/6324973)


On Fri, Aug 23, 2013 at 11:22 AM, Graydon Hoare gray...@mozilla.com wrote:

 On 13-08-23 11:16 AM, Patrick Walton wrote:
  On 8/23/13 11:15 AM, Graydon Hoare wrote:
  get_tydesc::T(). This is the foo vs foo:: syntax papercut. Gets
  everyone, sorry. It's the price of using  for type parameters rather
  than []. We need a better error message for it.
 
  Actually, [] would have the same problem, because of array indexing.

 Naturally, which is why array indexing (way back when) was foo.(index).
 But it was a throwaway comment; this is all very much water under the
 bridge, not in any way suggesting we revisit.

 -Graydon

 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Michael Sullivan
And here is another implementation of the same interface, implemented in a
much more brute force way. It is probably more efficient that the above,
and also about 5% as elegant.

mod UnsafeUniversal {
use std::managed;
use std::cast;

// We use pointers as our tags, since they are easy to generate
// uniquely and compare for equality. Uniquely generated integers
// might be better, but this is really simple and kind of cute.
type InnerTag = @();
fn new_inner_tag() - InnerTag { @() }
fn tag_eq(x: InnerTag, y: InnerTag) - bool {
managed::ptr_eq(x, y)
}

pub struct Univ {
tag: InnerTag,
value: @()
}

pub struct TagA {
priv inner: InnerTag
}

pub fn new_tagA:'static() - TagA {
Tag { inner: new_inner_tag() }
}

pub fn injectA:Clone+'static(tag: TagA, x: A) - Univ {
Univ {
tag: tag.inner,
value: unsafe { cast::transmute(@(x.clone())) }
}
}

pub fn projectA:Clone+'static(tag: TagA, x: Univ) - OptionA {
if tag_eq(tag.inner, x.tag) {
let ptr: @A = unsafe { cast::transmute(x.value) };
Some((*ptr).clone())
} else {
None
}
}
}


On Fri, Aug 23, 2013 at 4:54 PM, Michael Sullivan su...@msully.net wrote:

 So, as it turns out, something closely related can be implemented in
 completely safe rust.

 (The ideas here are based on http://mlton.org/UniversalType and the
 presentation of extensible types from my undergrad PL class. The
 implementation is based on the mlton UniversalType page, but I change the
 interface to be more like extensible types. If anybody cares, SML code for
 this is https://gist.github.com/msullivan/6324908.)

 We can implement a universal type that values of any (cloneable, not
 containing borrowed pointers) type can be injected to. The catch is that
 the values aren't actually keyed by the type, but by tags that are
 generated at runtime. This is sometimes useful (you can distinguish between
 different classes of values of the same type) and sometimes annoying (you
 have to manage the tags).

 The implementation here is pretty clever, but also kind of silly. It would
 probably actually be better in practice to do something unsafe internally
 with dynamically generated tag values.

 mod ClosureUniversal {
 // A value of universal type is a pair of functions.  store will
 // write the underlying value into the associated tag, while clear
 // will erase the data in the tag to prevent space leaks.
 pub struct Univ {
 priv store: @fn(),
 priv clear: @fn()
 }

 // A tag is a mutable option used as a scratch space to write
 // into when inspecting a tag.
 pub struct TagA {
 priv r: @mut OptionA
 }

 pub fn new_tagA:'static() - TagA {
 Tag { r: @mut None }
 }

 pub fn injectA:Clone+'static(tag: TagA, x: A) - Univ {
 Univ {
 store: || *tag.r = Some(x.clone()),
 clear: || *tag.r = None
 }
 }

 pub fn projectA:Clone+'static(tag: TagA, x: Univ) - OptionA {
 // Cause the value to be written into its tag. If the universal
 // value was injected with our tag, then it will be in tag.r.
 (x.store)();
 // Read out the value.
 let res = (*tag.r).clone();
 // Clear the value, to prevent space leaks.
 (x.clear)();
 res
 }
 }


 fn main() {
 use ClosureUniversal::*;

 // Create some tags
 let int_tag = new_tag::int();
 let str_tag = new_tag::~str();

 // Create some universal values with those tags
 let u1 = inject(int_tag, 5);
 let u2 = inject(int_tag, 6);
 let u3 = inject(str_tag, ~hello, world);

 // Try reading them
 println(fmt!(%?, project(int_tag, u1))); // Some(5)
 println(fmt!(%?, project(int_tag, u2))); // Some(6)
 println(fmt!(%?, project(int_tag, u3))); // None

 println(fmt!(%?, project(str_tag, u1))); // None
 println(fmt!(%?, project(str_tag, u2))); // None
 println(fmt!(%?, project(str_tag, u3))); // Some(~hello, world)

 // Try out a *different* int tag.
 let int_tag2 = new_tag::int();
 // It can not be used to read things created by the other int tag
 println(fmt!(%?, project(int_tag2, u1))); // None
 }

 (Code is also up at https://gist.github.com/msullivan/6324973)


 On Fri, Aug 23, 2013 at 11:22 AM, Graydon Hoare gray...@mozilla.comwrote:

 On 13-08-23 11:16 AM, Patrick Walton wrote:
  On 8/23/13 11:15 AM, Graydon Hoare wrote:
  get_tydesc::T(). This is the foo vs foo:: syntax papercut. Gets
  everyone, sorry. It's the price of using  for type parameters rather
  than []. We need a better error message for it.
 
  Actually, [] would have the same problem, because of array indexing.

 Naturally, which is why array indexing (way back when) was foo.(index).
 But it was a throwaway comment; this is all very much water 

Re: [rust-dev] Dynamic in Rust

2013-08-23 Thread Sebastian Sylvan
On Thu, Aug 22, 2013 at 9:49 PM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Is it possible to implement something like Haskell's Dynamic value holder
 in Rust?


I'm sure you've all seen it, but C# has something similar but a lot more
powerful. Basically, it has support for allowing runtime resolution of
types if they are declared as having the dynamic type. But it's even
better, the specification for how that resolution happens is defined in a
library. This way you can work directly with dynamic values without having
to cast them first (e.g. imagine just dotting your way through a JSON
document and parse it on-demand).

See
For how it's used:
http://msdn.microsoft.com/en-us/library/vstudio/dd264736.aspx
For how to implement dynamic libraries (e.g. decide what happens when a
field is accessed, or a method is called, on your dynamic objects):
http://msdn.microsoft.com/en-us/library/vstudio/system.dynamic.dynamicobject.aspx

-- 
Sebastian Sylvan
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] Dynamic in Rust

2013-08-22 Thread Oren Ben-Kiki
Is it possible to implement something like Haskell's Dynamic value holder
in Rust? (This would be similar to supporting C++'s dynamic_cast).
Basically, something like this:

pub struct Dynamic { ... }
impl Dynamic {
pub fn put(value: ~T) { ... }
pub fn get() - OptionT { ... }
}

I guess this would require unsafe code... even so, it seems to me that Rust
pointers don't carry sufficient meta-data for the above to work. A possible
workaround would be something like:

pub struct Dynamic { type_name: ~str, ... }
impl Dynamic {
pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
type_name, ... } }
pub fn get('a self, type_name: str) - Option'a T {
assert_eq!(type_name, self.type_name); ... } }
}

And placing the burden on the caller to always use the type name int when
putting or getting `int` values, etc. This would still require some sort of
unsafe code to cast the `~T` pointer into something and back, while
ensuring that the storage for the `T` (whatever its size is) is not
released until the `Dynamic` itself is.

(Why do I need such a monstrosity? Well, I need it to define a
`Configuration` container, which holds key/value pairs where whoever sets a
value knows its type, whoever gets the value should ask for the same type,
and the configuration can hold values of any type - not from a predefined
list of types).

Is such a thing possible, and if so, how?

Thanks,

Oren Ben-Kiki
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-22 Thread Abhijeet Gaiha
You could define an enum that encapsulates all known types.

enum monster {
 Integer(int),
 Float(float),

}

Then use a container for this type.
On Aug 23, 2013 10:20 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Is it possible to implement something like Haskell's Dynamic value holder
 in Rust? (This would be similar to supporting C++'s dynamic_cast).
 Basically, something like this:

 pub struct Dynamic { ... }
 impl Dynamic {
 pub fn put(value: ~T) { ... }
 pub fn get() - OptionT { ... }
 }

 I guess this would require unsafe code... even so, it seems to me that
 Rust pointers don't carry sufficient meta-data for the above to work. A
 possible workaround would be something like:

 pub struct Dynamic { type_name: ~str, ... }
 impl Dynamic {
 pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
 type_name, ... } }
 pub fn get('a self, type_name: str) - Option'a T {
 assert_eq!(type_name, self.type_name); ... } }
 }

 And placing the burden on the caller to always use the type name int
 when putting or getting `int` values, etc. This would still require some
 sort of unsafe code to cast the `~T` pointer into something and back, while
 ensuring that the storage for the `T` (whatever its size is) is not
 released until the `Dynamic` itself is.

 (Why do I need such a monstrosity? Well, I need it to define a
 `Configuration` container, which holds key/value pairs where whoever sets a
 value knows its type, whoever gets the value should ask for the same type,
 and the configuration can hold values of any type - not from a predefined
 list of types).

 Is such a thing possible, and if so, how?

 Thanks,

 Oren Ben-Kiki

 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-22 Thread Oren Ben-Kiki
That would require me to declare up front which types were usable and which
weren't. I'm looking for a solution where I don't need to do that; that is,
allow me to add new components to the system with new configuration
parameter types, without having to go to a central source location and
declare these types there.


On Fri, Aug 23, 2013 at 7:54 AM, Abhijeet Gaiha abhijeet.ga...@gmail.comwrote:

 You could define an enum that encapsulates all known types.

 enum monster {
  Integer(int),
  Float(float),
 
 }

 Then use a container for this type.
 On Aug 23, 2013 10:20 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Is it possible to implement something like Haskell's Dynamic value holder
 in Rust? (This would be similar to supporting C++'s dynamic_cast).
 Basically, something like this:

 pub struct Dynamic { ... }
 impl Dynamic {
 pub fn put(value: ~T) { ... }
 pub fn get() - OptionT { ... }
 }

 I guess this would require unsafe code... even so, it seems to me that
 Rust pointers don't carry sufficient meta-data for the above to work. A
 possible workaround would be something like:

 pub struct Dynamic { type_name: ~str, ... }
 impl Dynamic {
 pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
 type_name, ... } }
 pub fn get('a self, type_name: str) - Option'a T {
 assert_eq!(type_name, self.type_name); ... } }
 }

 And placing the burden on the caller to always use the type name int
 when putting or getting `int` values, etc. This would still require some
 sort of unsafe code to cast the `~T` pointer into something and back, while
 ensuring that the storage for the `T` (whatever its size is) is not
 released until the `Dynamic` itself is.

 (Why do I need such a monstrosity? Well, I need it to define a
 `Configuration` container, which holds key/value pairs where whoever sets a
 value knows its type, whoever gets the value should ask for the same type,
 and the configuration can hold values of any type - not from a predefined
 list of types).

 Is such a thing possible, and if so, how?

 Thanks,

 Oren Ben-Kiki

 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Dynamic in Rust

2013-08-22 Thread Abhijeet Gaiha
I think your second solution is what will work. You can use unsafe code and
a void pointer combined with a type descriptor string. I would probably
combine the void pointer and string in a struct.
On Aug 23, 2013 10:27 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 That would require me to declare up front which types were usable and
 which weren't. I'm looking for a solution where I don't need to do that;
 that is, allow me to add new components to the system with new
 configuration parameter types, without having to go to a central source
 location and declare these types there.


 On Fri, Aug 23, 2013 at 7:54 AM, Abhijeet Gaiha 
 abhijeet.ga...@gmail.comwrote:

 You could define an enum that encapsulates all known types.

 enum monster {
  Integer(int),
  Float(float),
 
 }

 Then use a container for this type.
 On Aug 23, 2013 10:20 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:

 Is it possible to implement something like Haskell's Dynamic value
 holder in Rust? (This would be similar to supporting C++'s dynamic_cast).
 Basically, something like this:

 pub struct Dynamic { ... }
 impl Dynamic {
 pub fn put(value: ~T) { ... }
 pub fn get() - OptionT { ... }
 }

 I guess this would require unsafe code... even so, it seems to me that
 Rust pointers don't carry sufficient meta-data for the above to work. A
 possible workaround would be something like:

 pub struct Dynamic { type_name: ~str, ... }
 impl Dynamic {
 pub fn put(type_name: str, value: ~T) { Dynamic { type_name:
 type_name, ... } }
 pub fn get('a self, type_name: str) - Option'a T {
 assert_eq!(type_name, self.type_name); ... } }
 }

 And placing the burden on the caller to always use the type name int
 when putting or getting `int` values, etc. This would still require some
 sort of unsafe code to cast the `~T` pointer into something and back, while
 ensuring that the storage for the `T` (whatever its size is) is not
 released until the `Dynamic` itself is.

 (Why do I need such a monstrosity? Well, I need it to define a
 `Configuration` container, which holds key/value pairs where whoever sets a
 value knows its type, whoever gets the value should ask for the same type,
 and the configuration can hold values of any type - not from a predefined
 list of types).

 Is such a thing possible, and if so, how?

 Thanks,

 Oren Ben-Kiki

 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev



___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev