At first read, I really like everything but the syntax's use of the period/dot and I am eager for something like this to exist in Go.
In my opinion the period is too inconspicuous-
Given: t := make([]T, 10)
Here are a few ideas:
var vt[]#T = t
var vt[]$T = t
var vt[]:T = t
var vt[]~T = t
--
---
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
On Tue, May 14, 2013 at 8:01 AM, Brad Fitzpatrick <brad...@golang.org> wrote:
Design doc for adding read-only slices to Go:https://docs.google.com/a/golang.org/document/d/1UKu_do3FRvfeN5Bb1RxLohV-zBOJWTzX0E8ZU1bkqX0/edit#heading=h.2wzvdd6vdi83
Comments welcome.So this is the (part of?) revised contribution process that you mentioned in another post?"The Go Language Change Proposal"
Will readonly slices support slicing? (i think it should, but it's not mentioned anywhere in
the docs)
i'm wondering if string could be treated as a [].byte?that is, at universal block, we have a declaration:type string [].byte
how does the readonly slices interact with the reflect system?will it introduce a new Kind or just a readonly flag for the slice kind (so as to pave the wayfor future extensions like readonly map)?
On Mon, May 13, 2013 at 5:42 PM, Brad Fitzpatrick <brad...@golang.org> wrote:One way to view this question is: are we introducing a new type, or
>>
>> how does the readonly slices interact with the reflect system?
>> will it introduce a new Kind or just a readonly flag for the slice kind
>> (so as to pave the way
>> for future extensions like readonly map)?
>
>
> I'm open to suggestions. You can imagine reflect.Value.Cap panicing if it's
> a read-only slice, for instance. I don't know whether keeping the same Kind
> would cause problems, if the representation changes.
>
> Alternatively, we could say that the representation of a read-only slice is
> the same as a slice, and cap() still works, but the cap(v) == len(v) always.
are we introducing a special case of an interface type?
In one sense
you are proposing a polymorphic interface type that supports the
operations
Len() int
At(int) T
Slice(int, int) [].T
If we view this as an interface type, then reflect should return the
original type. If not, then it could be a new Kind, or it could be
Slice with a new field.
Either way we need to think about converting a value out of the type
and back to []byte and/or string? Is that ever possible? Does it
always involve a copy? If we adopt the interface approach, should we
support x.([]byte) and x.(string)?
Either way we need to think about converting a value out of the type
and back to []byte and/or string? Is that ever possible? Does it
always involve a copy?
For what its worth, I think I like var vt[]:T = t best.
It is (subjectively) aesthetically clean and in Go has connotations related to slicing [x : y].
At first read, I really like everything but the syntax's use of the period/dot and I am eager for something like this to exist in Go.
In my opinion the period is too inconspicuous-
Given: t := make([]T, 10)
Here are a few ideas:
var vt[]#T = t
var vt[]$T = t
var vt[]:T = t
var vt[]~T = t
On Monday, May 13, 2013 7:01:57 PM UTC-5, Brad Fitzpatrick wrote:
Thanks Brad, that looks interesting. A few comments:On Mon, May 13, 2013 at 9:01 PM, Brad Fitzpatrick <brad...@golang.org> wrote:
> Design doc for adding read-only slices to Go:
>
> https://docs.google.com/a/golang.org/document/d/1UKu_do3FRvfeN5Bb1RxLohV-zBOJWTzX0E8ZU1bkqX0/edit#heading=h.2wzvdd6vdi83
>
> Comments welcome.
- The comparison with channels seems distracting
- Behavior when mutating the slice? Undefined, or defined with memory barriers?
- Should the printf family of functions change their formatting argument?
- Does it support + in a similar way to string?
- append?
If we introduce Immutability for slices we might as well introduce a universal immutability mechanism for all types.
- The comparison with channels seems distracting
Another thing to consider is if we have an immutable slice for types with methods. Whats the rules for methods for pointers? What if one of the slice elements modifies itself by referencing itself via a globally scoped pointer. Do we create a snapshot copies of the slice, and if so how can we update immutable slice to reflect changes made to the original mutable slice?
These are the kinds of things that need to be thought about.
Another thing to consider is if we have an immutable slice for types with methods. Whats the rules for methods for pointers?
What if one of the slice elements modifies itself by referencing itself via a globally scoped pointer.
Do we create a snapshot copies of the slice,
On Mon, May 13, 2013 at 10:41 PM, Brad Fitzpatrick <brad...@golang.org> wrote:
> On Mon, May 13, 2013 at 6:38 PM, Gustavo Niemeyer <gus...@niemeyer.net>
>> - Behavior when mutating the slice? Undefined, or defined with memoryThe behavior of []byte is defined with explicit synchronization. If
>> barriers?
>
> Undefined. Like I said in the doc, we already permit data races with []byte.
> This is no different.
you say undefined, then this is different.
>> - append?I suppose it should still be mentioned, at least to define the
>
> It's not mutable, so no.
cross-compatibility with []byte appending.
>>>> In one sense>> you are proposing a polymorphic interface type that supports theChannels feel a bit different to me: they remain channels, but
>> operations
>> Len() int
>> At(int) T
>> Slice(int, int) [].T
>> If we view this as an interface type, then reflect should return the
>> original type. If not, then it could be a new Kind, or it could be
>> Slice with a new field.
>
>
> In what sense do you view our current send-only channels?
converting to a send-only or receive-only channel eliminates certain
operations. Converting []byte to [].byte changes the nature of the
value, since it no longer has a capacity.
Converting string to
[].byte changes the meaning of the string significantly--e.g., range
and slice operations act differently.
I'm sure performance could be improved with this.It feels just different enough to feel confusing. I find the idea of a read-only map interesting. I think you've pulled a small thread on a much larger concept. Or tried to overly generalize a much smaller one (convert []byte <-> string w/o copy).I don't like introducing such a specialized type.Another option to creating a new read-only type is to create a region that can lock the mutability of a slice or un-lock the mutability of a string.bb := make([]byte, 10)lock(bb)defer unlock(bb)s := string(bb[:3]) // No copy.bb[2] = 'a' // Compile error or panic.However, I'm sure you've thought through all these options already.
That's true, it could work that way. I think one of Brad's goals isOn Mon, May 13, 2013 at 8:41 PM, Dan Kortschak
<dan.ko...@adelaide.edu.au> wrote:
> On Mon, 2013-05-13 at 20:27 -0700, Ian Lance Taylor wrote:
>> Converting []byte to [].byte changes the nature of the
>> value, since it no longer has a capacity.
>
> Why in principle should a [].byte not have a capacity? The elements of
> the view are not writable, but why should a holder of the [].byte not be
> able to expand the length to the capacity? They can make no change to
> the underlying data, all they can do is see it. The capacity means
> something slightly different here, but it still seems to have a meaning.
the copy-free conversion of string to [].byte,
and of course a string
does not have a capacity. But I suppose we could implement that by
setting the capacity of the [].byte to the length of the string.
Still, it's hard to see any particular use for a capacity for [].byte.
Your immutable slice proposal sounds very similar to strings in general. Therefore I was thinking if it's a good idea to change the string type to be an alias for [].byte in the first place (similar to rune and byte in the current specification). Have you thought about that?
On Tue, May 14, 2013 at 2:01 AM, Brad Fitzpatrick <brad...@golang.org> wrote:
If this change is made, why would you ever use strings in function parameters?> Design doc for adding read-only slices to Go:
>
> https://docs.google.com/a/golang.org/document/d/1UKu_do3FRvfeN5Bb1RxLohV-zBOJWTzX0E8ZU1bkqX0/edit#heading=h.2wzvdd6vdi83
>
> Comments welcome.
It seems to me that strings and read-only slices are very close to
each other semantically, and it will probably introduce the same sort
of confusion that already exists between make, new and composite
literals.
I'd rather put effort into making strings generate less garbage while
keeping their current semantics. That will probably include the
compiler doing some analysis,
but another idea that I haven't seen
floated yet is changing the runtime representation such that strings
converted from slices are copy on write whenever the slice data is
changed. You could probably smuggle some of the mechanism in via the
bounds check.
I've been reading through some of my code trying to work out what
benefit I would get from the extra cognitive load of [].byte. So far
it doesn't seem worth it.
A common problem in my code is when I see a []byte, I don't know if
some other reference will change it under me. The string type helps
readability by solving that problem.
--
---
You received this message because you are subscribed to a topic in the Google Groups "golang-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-dev/Y7j4B2r_eDw/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to golang-dev+...@googlegroups.com.
i don't think you'll be able to change any of the signatures of the
functions in the strings or bytes packages, otherwise you'll
break code that relies on the specific types of the functions.
e.g.
var f func(string, string) int = strings.Count
Then s/ const / ro /g for read only. This could be very helpful in writing stricter code in general. After all it is pretty close to the const pointer concept in c/c++ that has been proven to be well worth the effort in many cases.
Something like that would add complexities to the compiler and
depending on the specification, the runtime. But I would prefer it to
be there then in the user code base: "Oh, this package uses a
read-only slice, but this user uses a normal slice uhhh, ok, compiler,
I'll play your games and convert."
I don't think there is a functional difference between:
* read-only slices
* using unsafe to convert between bytes and strings
> You can't convert from [].T to []T, except using unsafe.Yes, in that direction you would have to copy to "convert".
But the problem is that for a long time you'll have old functions thatOn Tue, May 14, 2013 at 11:46 AM, Brad Fitzpatrick <brad...@golang.org> wrote:
> On Tue, May 14, 2013 at 8:42 AM, Daniel Theophanes <kard...@gmail.com>
> wrote:
>>
>> > You can't convert from [].T to []T, except using unsafe.
>>
>> Yes, in that direction you would have to copy to "convert".
>
>
> Which is great, because it's explicit and you see the cost.
>
> And the other direction is visually light-weight because it's free:
>
> var ts []T = ...
> var v [].T = ts
>
> No conversion necessary Just assignment.
take []byte, which is treated and documented as read-only, while new
ones take [].byte, which has its read-only status enforced by the
compiler. If the latter wants to call the former, it will have to
either make a copy or resort to unsafe hacks. For example:
// MyFunc doesn't modify b.
func MyFunc(b [].byte) bool {
return bytes.Contains(b, []byte("go")) // Not in Go1
}
I like the idea of cheap conversion between []byte and string, in one
form or another, but I don't think a new type is the answer.
Declaring
a function parameter as a string also adds some information about the
expected content. It usually means "this value is text in UTF-8
encoding, not data."
A package byteviews could implement then the read-only portions of strings and bytes package.
Instead of providing read-only slices in general and even for slices of pointers, providing byteviews to everything that contains neither padding nor pointers might be useful.
Design doc for adding read-only slices to Go:https://docs.google.com/a/golang.org/document/d/1UKu_do3FRvfeN5Bb1RxLohV-zBOJWTzX0E8ZU1bkqX0/edit#heading=h.2wzvdd6vdi83
Comments welcome.
--
I agree with @jan and @robin in that the perceived motivation for this is at least partly encroaching on what today's escape analysis, or that in the near future could certainly do to minimize the number of []byte <-> string copies; from what I've gleaned, the missing piece of this puzzle is compiler code that actually uses the results of existing analysis to prevent copies. Moreover, there'd be some places where static analysis would do a better job than the proposal, even with the proposal's own types, since _semantically_ you can't pass a [].byte into a string without a copy. Because of this, I'm only considering the aspects of the proposal that are not concerned with solving the perceived garbage problem.
Also, there's something to be said for hiding data behind functions and channels for readability' sake: Go currently has a simple "if you can see it, you can modify it" expectation that this proposal would violate, since it'd allow data to (at least under some circumstances) be safely used as its own API. The proposal does not use alternative syntax for accessing roslices, which is a good thing, though it does mean that readonly and mutable slices are only distinguishable at the declaration site, decreasing readability. Right now, exported package level variables can be modified by any importers; except in special circumstances (like an exported var of a non-exported type), this proposal wouldn't prevent anyone from replacing the referenced slice outright -- it'd just prevent modification of the original. Semantically, there wouldn't be much difference if that global var was the only reference, yet many programmers may see this proposal and assume it applies to the slice value in addition to the backing array.There's also a notable potential for abuse here. bufio.Reader's ReadSlice method doesn't return a copy of the internal buffer, but that's not a problem, since the Reader will blindly overwrite those contents on the next method call; in designing such an API, many would choose to return a [].byte instead of []byte for this same method, but that would not add any security in this case, and would be stealing away a scratch buffer that the application could temporarily use for its own purposes (instead forcing the application to create more garbage if it needed to manipulate the results).The reduction of library surface area is positive, but unless we could completely eliminate either the bytes or the strings package (not that we could before 2.x anyway), it seems better not to try, and instead decrease footprint by making all applicable strings functions offload onto bytes.@rog, regarding `var f func(string, string) int = strings.Count`, some, but not all, of this could be addressed by (controversially) modifying assignability rules such that a function type's assignability is transitively based on the assignability of its parameter types (in this case, making all assignability relationships like aliases). For example:func F(string) string {}func G([].byte) [].byte {}var (f1 func(string) [].byte = F // OK: return string assignable to [].bytef2 func([].byte) string = F // NO: param [].byte not assignable to stringg1 func(string) [].byte = G // OK: param string assignable to [].byteg2 func([].byte) string = G // NO: return [].byte not assignable to string)A positive point: it would also mean that `func(io.ReadSeeker)` is assignable to `func(io.Reader)`. In any case, this certainly brings readability down, though. A negative point: for maximum ease of use, with this we may start to see APIs like `func([].byte) string`, since it could take a string or []byte, yet be assigned into either a string or [].byte.The issue @rsc mentioned with converting to `bytes.TrimSpace([].byte) [].byte` could be remedied by allowing a language exception for the caller of such a function: if the caller passes a []T (which is converted into a [].T), then the caller can assign the result back into a []T if the function result references the same memory as the parameter. This raises a few issues: 1) the compiler would have to verify that result is derived from the input (which may not be trivial), 2) there'd be no syntax to indicate that a function can be used in this "temporarily immutable" way, requiring additional documentation guidelines instead, and 3) type inference would be problematic: should it be inferred as []T because the input happened to be []T, or inferred as [].T because it's documented that way?
--
A positive point: it would also mean that `func(io.ReadSeeker)` is assignable to `func(io.Reader)`.
The issue @rsc mentioned with converting to `bytes.TrimSpace([].byte) [].byte` could be remedied by allowing a language exception for the caller of such a function: if the caller passes a []T (which is converted into a [].T), then the caller can assign the result back into a []T if the function result references the same memory as the parameter.
@david: if roslices are forced to have cap == len (or no cap), ...
Otherwise, it'd be problematic when cap != len; should we panic at runtime, or prevent appends to roslices, or just always force an allocation? In either case, the append question is just a convenience (and shouldn't be a blocker), as `append(append([]T(nil), src...), extra...)` is roughly equivalent to `append(src, extra...)`.
# Transitive immutability:
# Tack-on proposal:Extend non-copy convertibility to cover read-only slice views of arbitrary compatibily aligned data. For example, anything would be non-copy convertible to a [].byte, since everything aligns to a multiple of one byte.
Though this is vey old thread, I like to add my opinions to push this feature to be added to Go ASAP.
--
You received this message because you are subscribed to a topic in the Google Groups "golang-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-dev/Y7j4B2r_eDw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.