FAQ
Could that be possible in go? For instance, I would like to create a
generic Stack interface-able by channels in which the user code is:
*
*
*// For ints*
*pushInterface := make(chan int)*
*popInterface := make(chan int)*
*CreateNewStackWith(pushInterface, popInterface)*
*pushInterface <- 1*
*pushInterface <- 2*
*two := <- popInterface*
*pushInterface <- "compile error"*

*//For strings*
*pushInterface := make(chan string)*
* popInterface := make(chan string)*
* CreateNewStackWith(pushInterface, popInterface)*
* pushInterface <- "1"*
* pushInterface <- "2"*
* two := <- popInterface*
* pushInterface <- 0xDEADC0DE*

Is it possible to design such a *CreateNewStackWith*? I'm aware "*chan int*"s
cannot be casted to "*chan interface{}*" for obvious reasons. But maybe
it's possible with a runtime conversion or something. I don't care how bad
the implementation of *CreateNewStackWith* is. I just care about the client
code been clean and without casts and* interface{}*s

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Egon at Aug 27, 2013 at 9:28 am

    On Tuesday, August 27, 2013 4:29:35 AM UTC+3, w5q...@gmail.com wrote:
    Could that be possible in go? For instance, I would like to create a
    generic Stack interface-able by channels in which the user code is:
    *
    *
    *// For ints*
    *pushInterface := make(chan int)*
    *popInterface := make(chan int)*
    *CreateNewStackWith(pushInterface, popInterface)*
    *pushInterface <- 1*
    *pushInterface <- 2*
    *two := <- popInterface*
    *pushInterface <- "compile error"*

    *//For strings*
    *pushInterface := make(chan string)*
    * popInterface := make(chan string)*
    * CreateNewStackWith(pushInterface, popInterface)*
    * pushInterface <- "1"*
    * pushInterface <- "2"*
    * two := <- popInterface*
    * pushInterface <- 0xDEADC0DE*

    Is it possible to design such a *CreateNewStackWith*? I'm aware "*chan int
    *"s cannot be casted to "*chan interface{}*" for obvious reasons. But
    maybe it's possible with a runtime conversion or something. I don't care
    how bad the implementation of *CreateNewStackWith* is. I just care about
    the client code been clean and without casts and* interface{}*s
    You probably can do something take "interface{}"-s as arguments to
    CreateNewStackWith and then use reflection to do the sends and receives.
    http://jimmyfrasche.github.io/go-reflection-codex/#synchronous-communication should
    come in handy. Whether it's a good idea I'm not so sure.

    Anyway the main problem you'll have is when doing pop --> you can't have
    enforced ordering on it. For example, let's say you put a value into the
    stack, now the pop channel should schedule a value into it, so the recv
    could work. But if a new value comes in you must change the value in the
    pop channel.

    Essentially you need this logic, in a way that it's not a "busy loop":

    stack := make([]int)

    send := make(chan int)
    recv := make(chan int) // must be synchronized

    go func(){
    for {
    // first make sure there's nothing in recv
    prev, ok := <-recv
    if ok {
    stack = append(stack, prev)
    }
    // put all the new items into stack
    for new, ok := <-send; ok {
    stack = append(stack, new)
    }
    // keep one item in recv
    if len(stack) > 0 {
    recv <- stack[len(stack)-1]
    stack = stack[:len(stack)-1]
    }
    // probably should yield here
    }
    }

    I'm not even sure if it's possible to not make it busy - you would need a
    select over a 1) receiving a value from "send" channel and sending a "recv"
    value. And I'm not sure how to wait for the "recv" event.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • W5qth8 at Aug 27, 2013 at 3:53 pm
    I see the problem of *pop* you're talking about. But the whole idea was to
    use channels for generic input/output. So, maybe the interface to push a
    value could be: "PrepareToPush(); send <- 8" and the interface to pop
    could be "PrepareToPop(); v := <- recv" and the problem you're talking
    about is "solved" (in the case I in fact understood it).

    The real problem was how to use those interface{} parameters (which are
    actually channels) as channels. I will try the reflection way you mencioned
    (I'm not with a go compiler right now) and reply later.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • W5qth8 at Aug 31, 2013 at 6:45 pm
    Implementing using reflection worked as expected. So, just for
    completeness, this is my implementation of a Generic Stack. The stack code
    is ugly and full of reflection. However, the client code (although not
    idiomatic go code) doesn't use reflection, casts, interface{}'s, and has
    compile-time type checking -- i.e. you can't 'push' an integer into a
    string stack. I know it's no big deal, but maybe this example has some
    value on the "not supporting generics is a deal breaker" rant:


    *package main
    import "fmt"
    import "reflect"

    type Stack struct {
         PrePush func() // Call this before pushing data into the IN socket
         PrePop func() // Call this before poping from OUT socket
    }

    type StkNode struct {
         Info reflect.Value
         Next *StkNode
    }

    func CreateBox(in interface{}, out interface{}) Stack {
         var top *StkNode = nil

         prePush := func() {
             go func() {
                 newData,_ := reflect.ValueOf(in).Recv()
                 top = &StkNode{newData, top}
             }()
         }

         prePop := func() {
             go func() {
                 if (top == nil) {
                     panic("TODO: error handle an MT stack")
                 }
                 data := top.Info
                 reflect.ValueOf(out).Send(data)
                 top = top.Next
             }()
         }
         return Stack{prePush,prePop}
    }

    func main() {
         fmt.Print("Using Stack with ints: ");
         inInt, outInt := make(chan int), make(chan int)
         StackOfInt := CreateBox(inInt, outInt)

         StackOfInt.PrePush(); inInt <- 5
         StackOfInt.PrePush(); inInt <- 1
         StackOfInt.PrePush(); inInt <- 3
         StackOfInt.PrePop(); fmt.Print(<-outInt)
         StackOfInt.PrePush(); inInt <- 4
         StackOfInt.PrePush(); inInt <- 1

         for i := 0; i < 4; i = i + 1 {
             StackOfInt.PrePop(); fmt.Print(<-outInt)
         }

         fmt.Print("\nUsing Stack with strings:")

         inStr, outStr := make(chan string), make(chan string)
         StackOfDouble := CreateBox(inStr, outStr)

         StackOfDouble.PrePush(); inStr <- "264338327950288"
         StackOfDouble.PrePush(); inStr <- "."
         StackOfDouble.PrePush(); inStr <- "3"
         StackOfDouble.PrePop(); fmt.Print(<-outStr)
         StackOfDouble.PrePop(); fmt.Print(<-outStr)
         StackOfDouble.PrePush(); inStr <- "8979323846"
         StackOfDouble.PrePush(); inStr <- "1415926535"

         for i := 0; i < 3; i = i + 1 {
             StackOfDouble.PrePop(); fmt.Print(<-outStr)
         }
         fmt.Println("")
    }
    *

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • W5qth8 at Aug 31, 2013 at 6:46 pm
    %s/CreateBox/CreateStack/g

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedAug 27, '13 at 2:05a
activeAug 31, '13 at 6:46p
posts5
users2
websitegolang.org

2 users in discussion

W5qth8: 4 posts Egon: 1 post

People

Translate

site design / logo © 2021 Grokbase