* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
@ 2011-05-16 8:57 ` Joel Reymont
2011-05-16 9:31 ` Joel Reymont
` (6 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 8:57 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
On May 16, 2011, at 9:07 AM, Gabriel Scherer wrote:
> If "call" is the only thing you wish to do on your array, you don't need such an ugly solution. "sock" and "mask" being constants for a given item, you can simply capture them in a closure.
All I want to do (and must do) is call "poll" on the poll item set.
There are no callbacks since I'm checking to see what socket has data and then issuing a "receive data" call on that socket.
> Joel must have an use case in mind which is actually type-safe; maybe it's only the callback as you demonstrated (I fail to see its usefulness, but I don't know anything about ZeroMQ), maybe it's something a bit more complicated. But we won't be able to give him a satisfying solution unless he describes more precisely what this type-safe use is.
My type safe use is exactly what Unix select does, i.e. determine what socket has data available.
> Joel, may you be more explicit as to what you want to do with those "poll_item" array. More precisely, how do you plan to *use* the data in the array?
I need to check the mask for each item in the returned array to see what socket has data. Then I need to read data from the socket.
I suspect I'll need to change how the socket is typed to convert to a variant of socket types which can be stored easily into a poll set. I really don't know why Socket is typed as it is, maybe Pedro (the creator of ocaml-zmq) can explain.
Thanks, Joel
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
2011-05-16 8:57 ` Joel Reymont
@ 2011-05-16 9:31 ` Joel Reymont
2011-05-16 9:58 ` Joel Reymont
` (5 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 9:31 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
The socket is typed the way it is because of these two functions:
val subscribe : sub t -> string -> unit
val unsubscribe : sub t -> string -> unit
Meaning that you should only be able to use subscribe and unsubscribe on sockets created with type sub Socket.t ('a = sub).
This reminds me an example with phantom types I saw somewhere, possibly in the context of Xen and its OCaml bindings.
This is where you can only use certain functions that access memory on memory that has been initialized.
Maybe phantom types are called for here.
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
2011-05-16 8:57 ` Joel Reymont
2011-05-16 9:31 ` Joel Reymont
@ 2011-05-16 9:58 ` Joel Reymont
2011-05-16 10:05 ` Joel Reymont
` (4 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 9:58 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
What about this?
It almost works, e.g.
File "ZMQ.mli", line 125, characters 7-99:
Error: A type variable is unbound in this type declaration.
In type
([> `Dealer | `Pair | `Pub | `Pull | `Push | `Rep | `Req | `Router | `Sub ]
as 'a)
Socket.t * event_mask the variable 'a is unbound
I marked line 125 below.
Thanks, Joel
---
module Socket :
sig
type 'a t
type 'a kind
val pair : [`Pair] kind
val pub : [`Pub] kind
val sub : [`Sub] kind
val req : [`Req] kind
val rep : [`Rep] kind
val dealer : [`Dealer] kind
val router : [`Router] kind
val pull : [`Pull] kind
val push : [`Push] kind
...
val subscribe : [`Sub] t -> string -> unit
val unsubscribe : [`Sub] t -> string -> unit
end
module Device :
sig
val streamer : [`Pull] Socket.t -> [`Push] Socket.t -> unit
val forwarder : [`Sub] Socket.t -> [`Pub] Socket.t -> unit
val queue : [`Router] Socket.t -> [`Dealer] Socket.t -> unit
end
module Poll :
sig
type t
type event_mask = In | Out | In_out
type poll_socket = [>`Pair|`Pub|`Sub|`Req|`Rep|`Dealer|`Router|`Pull|`Push] Socket.t (* <---- line 125 *)
type poll_item = (poll_socket * event_mask)
val of_poll_items : poll_item array -> t
val poll : ?timeout: int -> t -> poll_item array
end
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
` (2 preceding siblings ...)
2011-05-16 9:58 ` Joel Reymont
@ 2011-05-16 10:05 ` Joel Reymont
2011-05-16 12:02 ` Joel Reymont
` (3 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 10:05 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
Typing it this way
module Poll :
sig
type t
type poll_socket = [`Pair|`Pub|`Sub|`Req|`Rep|`Dealer|`Router|`Pull|`Push] Socket.t
type poll_item = (poll_socket * event_mask)
val of_poll_items : poll_item array -> t
...
end
I get a different error when using of_poll_items with two different socket types:
File "src/dawn.ml", line 73, characters 44-52:
Error: This expression has type [ `Pub ] ZMQ.Socket.t * ZMQ.Poll.event_mask
but an expression was expected of type
[ `Pull ] ZMQ.Socket.t * ZMQ.Poll.event_mask
These two variant types have no intersection
This is the difference between
type poll_socket = [>...] Socket.t
and
type poll_socket = [...] Socket.t
What is the proper way to type this?
Thanks, Joel
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
` (3 preceding siblings ...)
2011-05-16 10:05 ` Joel Reymont
@ 2011-05-16 12:02 ` Joel Reymont
2011-05-16 12:32 ` Joel Reymont
` (2 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 12:02 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
Here's the problem reduced to a single file.
Two files, actually, the first one showing my intended use.
The error is
File "zmq.ml", line 72, characters 7-86:
Error: A type variable is unbound in this type declaration.
In type
([< `Dealer | `Pair | `Pub | `Pull | `Push | `Rep | `Req | `Router | `Sub ]
as 'a)
Socket.t the variable 'a is unbound
Thanks, Joel
P.S.
--- foo.ml
#use "topfind";;
#require "zmq";;
open ZMQ;;
open ZMQ.Socket;;
open ZMQ.Poll;;
let context = init ();;
let pub_endpoint = "tcp://127.0.0.1:9997";;
let pull_endpoint = "tcp://127.0.0.1:9996";;
let pub =
let sock = Socket.create context pub in
connect sock pub_endpoint;
sock;;
let pull =
let sock = Socket.create context pull in
connect sock pull_endpoint;
sock;;
let timeout = 1000000 (* 1s *);;
let poll_set = of_poll_items [| pull, In; pub, Out |] in
match poll ~timeout poll_set with
| [| pull, In |] ->
let msg = recv pull in
()
| _ ->
()
;;
--- zmq.ml
module Socket :
sig
type 'a t
type 'a kind
val pair : [`Pair] kind
val pub : [`Pub] kind
val sub : [`Sub] kind
val req : [`Req] kind
val rep : [`Rep] kind
val dealer : [`Dealer] kind
val router : [`Router] kind
val pull : [`Pull] kind
val push : [`Push] kind
val create : 'a kind -> 'a t
val connect : 'a t -> string -> unit
val bind : 'a t -> string -> unit
val subscribe : [`Sub] t -> string -> unit
val unsubscribe : [`Sub] t -> string -> unit
end = struct
type 'a t = int
type 'a kind = int
let pair = 0
let pub = 1
let sub = 2
let req = 3
let rep = 4
let dealer = 5
let router = 6
let pull = 7
let push = 8
let create kind = 1
let connect sock endpoint = ()
let bind sock endpoint = ()
let subscribe socket new_subscription = ()
let unsubscribe socket old_subscription = ()
end
module Device :
sig
val streamer : [`Pull] Socket.t -> [`Push] Socket.t -> unit
val forwarder : [`Sub] Socket.t -> [`Pub] Socket.t -> unit
val queue : [`Router] Socket.t -> [`Dealer] Socket.t -> unit
end = struct
let streamer sock1 sock2 = ()
let forwarder sock1 sock2 = ()
let queue sock1 sock2 = ()
end
module Poll :
sig
type t
type event_mask = In | Out | In_out
type poll_socket = [<`Pair|`Pub|`Sub|`Req|`Rep|`Dealer|`Router|`Pull|`Push] Socket.t
type poll_item = (poll_socket * event_mask)
val of_poll_items : poll_item array -> t
end = struct
type t = string
let of_poll_items items = "create poll set"
end
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
` (4 preceding siblings ...)
2011-05-16 12:02 ` Joel Reymont
@ 2011-05-16 12:32 ` Joel Reymont
2011-05-16 13:02 ` Joel Reymont
2011-05-17 4:26 ` Goswin von Brederlow
7 siblings, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 12:32 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
Everything in a single file is here:
https://gist.github.com/974321
Can repost to the list if needed.
Compiling gives the error.
File "zmq.ml", line 108, characters 42-50:
Error: This expression has type [ `Pub ] Socket.t * Poll.event_mask
but an expression was expected of type
[ `Pull ] Socket.t * Poll.event_mask
These two variant types have no intersection
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
` (5 preceding siblings ...)
2011-05-16 12:32 ` Joel Reymont
@ 2011-05-16 13:02 ` Joel Reymont
2011-05-16 13:39 ` Gabriel Scherer
2011-05-17 4:26 ` Goswin von Brederlow
7 siblings, 1 reply; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 13:02 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
Issue solved thanks to Anil Madhavapeddy.
val pair : [>`Pair] kind
val pub : [>`Pub] kind
etc.
and then
type poll_socket = [`Pair|`Pub|`Sub|`Req|`Rep|`Dealer|`Router|`Pull|`Push] Socket.t
type poll_item = (poll_socket * event_mask)
val of_poll_items : poll_item array -> t
This does it!
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 13:02 ` Joel Reymont
@ 2011-05-16 13:39 ` Gabriel Scherer
2011-05-16 13:46 ` Joel Reymont
2011-05-16 14:02 ` Joel Reymont
0 siblings, 2 replies; 18+ messages in thread
From: Gabriel Scherer @ 2011-05-16 13:39 UTC (permalink / raw)
To: Joel Reymont; +Cc: Goswin von Brederlow, caml-list
[-- Attachment #1: Type: text/plain, Size: 2198 bytes --]
The problem with this solution, if I understand it correctly, is that it
amounts to losing type information. Your values begin with some type
information attached to them, that allows more fine-grained typing of some
information (subscription), but then you coerce them into a big magma of
"everything" to put them in the array, and the type information is lost.
When you get back an element of this array, you don't know anymore if it was
a `Pair or a `Sub for example. You probably won't be able to use the more
restrictive operations of your interface.
A solution to this problem would be to tag each item with its provenance
type, so that you can regain fine-grained types dynamically :
type any_poll =
| Pair of pair poll
| Sub of sub poll
| ...
Then, given an array of `any_poll` elements, you can pattern match and, if
it's a `Sub`, you have a `sub poll` available. I think this is more precise
than your current solution.
More generally, I don't think the polymorphic variants bring anything more
that what you could have with simple abstract types here. For example to
coerce everything to a common type with the `pair poll`, `sub poll` solution
you could define a `any` abstract datatype and provide a `val lose_type_info
: 'a poll -> any poll` function. Unless I'm mistaken, this is equivalent to
your current solution, and shields you of any superfluous polymorphic
variant oddities.
On Mon, May 16, 2011 at 3:02 PM, Joel Reymont <joelr1@gmail.com> wrote:
> Issue solved thanks to Anil Madhavapeddy.
>
> val pair : [>`Pair] kind
> val pub : [>`Pub] kind
>
> etc.
>
> and then
>
> type poll_socket = [`Pair|`Pub|`Sub|`Req|`Rep|`Dealer|`Router|`Pull|`Push]
> Socket.t
> type poll_item = (poll_socket * event_mask)
>
> val of_poll_items : poll_item array -> t
>
> This does it!
>
> --------------------------------------------------------------------------
> - for hire: mac osx device driver ninja, kernel extensions and usb drivers
> ---------------------+------------+---------------------------------------
> http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
> ---------------------+------------+---------------------------------------
>
>
>
>
[-- Attachment #2: Type: text/html, Size: 2911 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 13:39 ` Gabriel Scherer
@ 2011-05-16 13:46 ` Joel Reymont
2011-05-16 14:02 ` Joel Reymont
1 sibling, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 13:46 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
Gabriel,
On May 16, 2011, at 3:39 PM, Gabriel Scherer wrote:
> A solution to this problem would be to tag each item with its provenance type, so that you can regain fine-grained types dynamically :
>
> type any_poll =
> | Pair of pair poll
> | Sub of sub poll
> | ...
I do agree with you on the losing of types.
I cannot have a pair poll, sub poll, etc. because poll takes in the array of 'any socket' types.
I wonder if the right solution here is -not- to return the socket from the call to poll but just return the flags.
You can then get hold of the socket itself in the original poll set and that socket would have the original type information.
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 13:39 ` Gabriel Scherer
2011-05-16 13:46 ` Joel Reymont
@ 2011-05-16 14:02 ` Joel Reymont
2011-05-16 14:06 ` Gabriel Scherer
1 sibling, 1 reply; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 14:02 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, caml-list
On May 16, 2011, at 3:39 PM, Gabriel Scherer wrote:
> More generally, I don't think the polymorphic variants bring anything more that what you could have with simple abstract types here.
How would I accomplish this with simple abstract types?
For example, how do I do this?
module Device :
sig
val streamer : [`Pull] Socket.t -> [`Push] Socket.t -> unit
val forwarder : [`Sub] Socket.t -> [`Pub] Socket.t -> unit
val queue : [`Router] Socket.t -> [`Dealer] Socket.t -> unit
end
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 14:02 ` Joel Reymont
@ 2011-05-16 14:06 ` Gabriel Scherer
2011-05-16 14:08 ` Joel Reymont
0 siblings, 1 reply; 18+ messages in thread
From: Gabriel Scherer @ 2011-05-16 14:06 UTC (permalink / raw)
To: Joel Reymont; +Cc: caml-list
[-- Attachment #1: Type: text/plain, Size: 1262 bytes --]
module Device : sig
type pull
type push
type pub
type sub
type router
type dealer
val streamer : pull Socket.t -> push Socket.t -> unit
val forwarder : sub Socket.t -> pub Socket.t -> unit
val queue : router Socket.t -> dealer Socket.t -> unit
end
On Mon, May 16, 2011 at 4:02 PM, Joel Reymont <joelr1@gmail.com> wrote:
>
> On May 16, 2011, at 3:39 PM, Gabriel Scherer wrote:
>
> > More generally, I don't think the polymorphic variants bring anything
> more that what you could have with simple abstract types here.
>
> How would I accomplish this with simple abstract types?
>
> For example, how do I do this?
>
> module Device :
> sig
>
> val streamer : [`Pull] Socket.t -> [`Push] Socket.t -> unit
> val forwarder : [`Sub] Socket.t -> [`Pub] Socket.t -> unit
> val queue : [`Router] Socket.t -> [`Dealer] Socket.t -> unit
>
> end
>
> --------------------------------------------------------------------------
> - for hire: mac osx device driver ninja, kernel extensions and usb drivers
> ---------------------+------------+---------------------------------------
> http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
> ---------------------+------------+---------------------------------------
>
>
>
>
[-- Attachment #2: Type: text/html, Size: 2765 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 14:06 ` Gabriel Scherer
@ 2011-05-16 14:08 ` Joel Reymont
0 siblings, 0 replies; 18+ messages in thread
From: Joel Reymont @ 2011-05-16 14:08 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: caml-list
On May 16, 2011, at 4:06 PM, Gabriel Scherer wrote:
> module Device : sig
> type pull
> type push
> type pub
> type sub
> type router
> type dealer
> val streamer : pull Socket.t -> push Socket.t -> unit
> val forwarder : sub Socket.t -> pub Socket.t -> unit
> val queue : router Socket.t -> dealer Socket.t -> unit
> end
This is very much how it was before and then I could not implement the poll
module Poll :
sig
type t
type event_mask = In | Out | In_out
type poll_socket = [`Pair|`Pub|`Sub|`Req|`Rep|`Dealer|`Router|`Pull|`Push] Socket.t
type poll_item = (poll_socket * event_mask)
val of_poll_items : poll_item array -> t
val poll : ?timeout: int -> t -> poll_item array
end
--------------------------------------------------------------------------
- for hire: mac osx device driver ninja, kernel extensions and usb drivers
---------------------+------------+---------------------------------------
http://wagerlabs.com | @wagerlabs | http://www.linkedin.com/in/joelreymont
---------------------+------------+---------------------------------------
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Caml-list] do i need a private row type?
2011-05-16 7:07 ` Gabriel Scherer
` (6 preceding siblings ...)
2011-05-16 13:02 ` Joel Reymont
@ 2011-05-17 4:26 ` Goswin von Brederlow
7 siblings, 0 replies; 18+ messages in thread
From: Goswin von Brederlow @ 2011-05-17 4:26 UTC (permalink / raw)
To: Gabriel Scherer; +Cc: Goswin von Brederlow, Joel Reymont, caml-list
Gabriel Scherer <gabriel.scherer@gmail.com> writes:
> On Mon, May 16, 2011 at 8:24 AM, Goswin von Brederlow <goswin-v-b@web.de>
> wrote:
>
> First thing is that if you have different 'a poll_items then you need to
> include a callback that accepts a matching 'a Socket.t. E.g.:
>
> type 'a poll_item = ('a Socket.t * event_mask * ('a Socket.t -> event_mask
> -> unit))
>
> Then you can make an unit poll_item array and use
>
> let set i (item : 'a poll_item) =
> array.[i] <- Obj.magic item
>
> let call i =
> let (sock, mask, fn) = array.[i]
> in
> fn sock mask
>
> The important part here is that you ensure the 'a Socket.t is only
> accessed through the callback. Only that will have the right type.
>
>
> If "call" is the only thing you wish to do on your array, you don't need such
> an ugly solution. "sock" and "mask" being constants for a given item, you can
> simply capture them in a closure.
>
> type poll_item_thunk = unit -> unit
>
> let set i (socket, event_mask, callback) =
> array.(i) <- (fun () -> callback socket event_mask);
>
> let call i = array.(i) ()
>
>
> There is no reasonable answer to "how do I force OCaml into breaking type
> safety ?". Joel must have an use case in mind which is actually type-safe;
> maybe it's only the callback as you demonstrated (I fail to see its usefulness,
> but I don't know anything about ZeroMQ), maybe it's something a bit more
> complicated. But we won't be able to give him a satisfying solution unless he
> describes more precisely what this type-safe use is.
This is still type safe given sufficient encapsulation in a module so it
can't be abused. But as I said, it is the dirty solution, like anything
requireing Obj.magic is. And you are right, if all you have is one
callback then a simple closure is better.
But you also need access to the Unix.file_descr underlying the socket to
select on it. And then you need a second callback to handle error
conditions. And then your socket probably has some state and things
become mutable and closures quickly become ugly and use up a lot more
memory if you have many sockets.
> The most general solution, as you alluded, is to use existential types. This
> can be done by an encoding into universal types (this is the "2 records"
> approach), or using first-class modules and abstract types.
I haven't tried this with first-class modules and the better support for
abstract types yet. But I would be interested to see in how they improve
on the 2 records solution.
Another thing I didn't mention is to use objects. This use case is
actually the poster child for objects with virtual functions.
> Joel, may you be more explicit as to what you want to do with those "poll_item"
> array. More precisely, how do you plan to *use* the data in the array?
MfG
Goswin
^ permalink raw reply [flat|nested] 18+ messages in thread