<veex>
the IwordI here. Why is it enclosed in pipes?
<bnagy>
because syntax
<apeiros_>
it's the argument the block takes
<veex>
how does ruby know that 'word' means the strings within the array?
<apeiros_>
as I said, it's like an anonymous function. so it consists of argument + body
<apeiros_>
it knows by collect passing the individual words in.
<apeiros_>
yielding, in ruby terminology. since the keyword to call the block is `yield`
<veex>
yes but why not name word something like strings
<apeiros_>
that is, collect calls the block once for each element in the array.
<veex>
would it still know to do the same thing?
<apeiros_>
it's a variable. you can name the variable whatever you want.
<apeiros_>
(as long as you stick to variable naming rules)
<veex>
it just knows that |word| means anything within the array so it could be |candy| and it would do the same as long as it was candy.upcase
<erikh>
apeiros_: thanks
<apeiros_>
veex: yes
<apeiros_>
actually it doesn't know "anything within the array"
tbuehlmann has joined #ruby-lang
<apeiros_>
it knows "passed in by collect"
yugui is now known as yugui_zzz
<veex>
ahh, okay, so it knows that lower_case is the array and since upper_case is being set to the array it knows that |word| is any constant attached to the variable uppcase
<bnagy>
veex: your last explanation wasn't even in any language I am able to parse, let alone correct :)
<veex>
crap
<erikh>
do you understand what's happening?
<veex>
No
<erikh>
ok, so in that code...
<andrewvos>
So, I want to buy a projector... Sadly, my imac isn't the best to output video to a projector because of it's location. THinking of getting one of those mini pcs. Thoughts?
<erikh>
there's an implicit block. there's one available to every method
<erikh>
I GOT THIS
<bnagy>
think of it like this. collect (the method) takes every element in a collection (like an Array) and throws it into the block you provide
<andrewvos>
Not exactly a ruby question, but haalp
<erikh>
self is our array in the case of ary.collect
<erikh>
we walk through self, yielding each object and pushing it to the new array
<apeiros_>
veex: lower_case is an array. you then call collect on it. collect goes through each element in the array lower_case and calls the block once for each of these elements
<erikh>
at the point of the yield, the block provided to collect is given x
<erikh>
and the evaluation is stored in the new array 'ret'
<erikh>
then we return the array.
<andrewvos>
Maybe a Mac Mini?
<apeiros_>
so the block is like a function. collect passes the element. you call upcase on it. the block returns that upper-cased string (since it's the last expression)
<apeiros_>
collect puts each of the return values into a new array (see erikh's code, how collect would look when written in ruby)
<apeiros_>
and collect then returns that new array.
<apeiros_>
you then assign the result of collect (that array of uppercased strings) to the variable upper_case
<veex>
This is great stuff. I'm reading through each comment and thinking
<apeiros_>
that's what goes on, step by step
<veex>
So the code you provided erik. The block is the def all the way ending with the .each before the { |x| ?
<erikh>
no.
<erikh>
hold on a sec.
<bnagy>
popcorn time again!
<erikh>
haha I'm not mad
<bnagy>
veex: the block is either do |block_arg| ... end or {|block_arg| ... }
<erikh>
actually, I need to run to the store and get caffeine
<erikh>
can someone explain implicit blocks and explicit ones?
<erikh>
I think that's the problem.
<bnagy>
the stuff in the pipes gives you a locally scoped reference to the arg, judt like def foo( method_arg )
<veex>
everything is the block except the pipes
<veex>
Everything within the { } is the block
<bnagy>
words.map HERE COMES THE BLOCK!!! {|word| word.upcase} THE BLOCK IS FINISHED NOW
<veex>
I feel stupid
<veex>
Okay, nice, so the block is that guy
<bnagy>
or do |word| word.upcase end if that's more to your taste
<veex>
Nice bnagy, I get what the block is, and the locally scoped reference object.
<bnagy>
a block is just a little chunk of code we can chuck around
<veex>
What's the diff between explicit and implicit block?
<bnagy>
you could make one like block= proc {|word| word.upcase}
<bnagy>
and then words.map &blk
<bnagy>
an implicit block is what you were doing before
charliesome has joined #ruby-lang
Defusal has joined #ruby-lang
Defusal has quit [Changing host]
Defusal has joined #ruby-lang
<veex>
what is an explicit block?
<bnagy>
what I just did then
perryh is now known as perryh_away
<veex>
I think I get it. Explicit is sort of a named method
fgomez has quit [Ping timeout: 240 seconds]
<bnagy>
basically when you define a method, you can see if there is an implicit block with block_given? and if there is , you can yield to it
<veex>
whereas implicit is anonymous within a code block
dejongge has joined #ruby-lang
<bnagy>
otherwise if you define your ethod like foo(arg, &blk) then you can take an explicit block
<bnagy>
and then blk.call or do whatever
zmack has joined #ruby-lang
<veex>
so explicit block can be passed as parameters
<veex>
whereas implicit blocks are anonymous and can't really be passed
<veex>
I can't call the implicit block on the words.upper_case. I'd have to call the class method?
* veex
feels hopeless
stardiviner has joined #ruby-lang
<bnagy>
no, you're just using random words
burgestrand has joined #ruby-lang
<bnagy>
don't worry about terminology, just worry about if you understand how it works
qwerxy has quit [Quit: offski]
<veex>
so implicit is random words
<veex>
that you've made up vs explicit being standardized words
<erikh>
not really.
<bnagy>
no "19:12 < veex> so explicit block can be passed as parameters
<bnagy>
19:12 < veex> whereas implicit blocks are anonymous and can't really be passed
<bnagy>
is random words
<bnagy>
sorry the line after, my mouse hates me
<erikh>
veex: is english your first language? not trying to be offensive, just curious if you'd be better suited to help in a different one.
zmack has quit [Ping timeout: 246 seconds]
<veex>
Yes, I'm an American. I'll try to write more clearly.
<veex>
I'm tired. I've been up all night but I usually write like that anyways. Perhaps I need to look at this visually. Are there any visual tools or websites that show this stuff visually?
AlHafoudh has joined #ruby-lang
<bnagy>
the poignant guide has cartoon rabbits
<erikh>
the text is about as visual as it gets
<veex>
I have a degree in computer science. I don't know why this is challenging me.
<erikh>
it's ok.
<veex>
You can laugh all you want...
<erikh>
I'm not. I'd suggest practicing with a few different styles and reading some code.
<bnagy>
+1 for writing code though - just write soe toy methods that use blocks in a few different ways
<erikh>
implementing something that uses Enumerable would be good practice too.
<veex>
I just don't understand explicit vs implicit blocks right now. I did get the first part where collect is working on the block array.
<erikh>
well
<erikh>
let's start at the top
<erikh>
you were having trouble with the terms?
<erikh>
let's google them and get definitions first.
<erikh>
additionally, seeing as it can't be any earlier than 3am in the states, I'd suggest getting some rest.
<veex>
I did quickly while chatting here.
<erikh>
we'll be here tomorrow.
<veex>
Yeah, I need some sleep. Where are you guys from?
<erikh>
I'm in silicon valley.
<veex>
That's awesome. San Mateo County?
<erikh>
yep.
<erikh>
menlo park.
<veex>
I worked at a startup out there. It was fascinating.
<erikh>
yeah it's a ... different place for sure
<veex>
Do you write Ruby or do Rails stuff all day?
<erikh>
ruby, C, shell, and chef
<erikh>
I'm in ops.
<veex>
OPS?
<erikh>
operations, system administration, make things go, etc.
<veex>
I do automated QA stuff. Mostly in C#
<erikh>
oh, neat. C# is a really neat langauge
jxie has quit [Ping timeout: 252 seconds]
<veex>
I am throwing myself completely into Rails and Ruby.
<erikh>
can't say I'm much for developing outside of vim, but it's not as bad as I predicted it to be
<erikh>
vsvim helped a lot :P
<erikh>
cooll
<veex>
We have mostly small conservative business in the middle of the United States. Most of it is maintenance work. Any new development is usually done by a small number of companies or consultants.
<erikh>
be sure to understand ruby thoroughly before diving into rails.
<erikh>
Sinatra might be a good first step if you're hell-bent on doing web stuff.
<apeiros_>
self.after_initialize(:generate_uid) <-- this means your model will get a new uuid each time it is initialized, that includes being read from the db. I doubt you want that.
<apeiros_>
AlHafoudh: also the reason why this is a #rubyonrails question
<erikh>
if it's already set, it doesn't try to overwrite it.
<AlHafoudh>
apeiros_: i asked there
<erikh>
oh, something you will see different in C#
<apeiros_>
ah, well, omit that. you do self.uid ||=.
<apeiros_>
AlHafoudh: so cross-poster… why am I even replying then…
<erikh>
veex: so x || y is 'if x is true, return it, else return y'
<erikh>
not Boolean.
<erikh>
the way ruby booleans work makes this possible
* apeiros_
really needs to finish that gist on proper cross-posting and start kicking people again…
<erikh>
apeiros_: eh
<erikh>
don't
<erikh>
it just doesn't happen that often
<apeiros_>
often enough.
<veex>
oh sorry apeiros_
<apeiros_>
or rather: too often
<AlHafoudh>
eh
<apeiros_>
veex: why?
<veex>
I am cross posting
<veex>
so the | | is an 'if..else' routine
<erikh>
it
<erikh>
it's not | |
<erikh>
it's ||=
<erikh>
'or equals'
<erikh>
just like || 'or' and = 'assignment'
<apeiros_>
'or assigns'`
<apeiros_>
?
<erikh>
oh derp
<erikh>
I'm tired.
<apeiros_>
^^
<veex>
so the || is or
<veex>
Got it
yannis has joined #ruby-lang
<burgestrand>
or is or, too! :d
<veex>
Yeah, I can see that self.after_initialize(:generate_uid) will generate a new user ID everytime this thing initializes
<apeiros_>
AlHafoudh: that whole thing is still a race conditions. even if (due to the nature of UUIDs) it is very unlikely to ever explode.
<erikh>
I'd really consider axing that database call if nothing else
<AlHafoudh>
apeiros_: yeah, I am fixing that now
<erikh>
try to insert it against a constraint
<erikh>
if it fails, retry
<erikh>
that will be much faster
<apeiros_>
sadly rails/ar has no proper mechanics to deal with insert-constraint-failures
<erikh>
it raises
<erikh>
well, save! does
<apeiros_>
yes, but where do you rescue?
<erikh>
begin; blah.foo = uid; blah.save!; rescue retry; end
<apeiros_>
the code dealing with it should be in the model. but you have no callback for that
<apeiros_>
erikh: yes. where is that code? it'll likely end up being in the controller, which is the wrong place.
<veex>
so the :generate_uid are symbols. How does Ruby know that generate creates a new uid?
<erikh>
apeiros_: right where he has it now
<erikh>
he could make a model method to do it too
<erikh>
but that seems kind of silly.
<erikh>
this is why I hate rails.
* erikh
grins.
<apeiros_>
erikh: then you'd have to call something else than save! and remember that
<veex>
do all parameters have to be symbols of the type :symbol notation?
<apeiros_>
and given that this is a piece of code to extend all models, and you could potentially have many of these, that way of dealing with it won't scale…
<erikh>
fair enough, I really don't want to think about this too hard.
<erikh>
the where has to go though
<apeiros_>
well, proper solution IMO would be to have proper callbacks to deal with insertion failures.
<erikh>
veex: it depends on the method.
<apeiros_>
so you could hook up on these and cause a retry. but rails doesn't have them.
<erikh>
mysql/pg/etc will raise
<erikh>
I think.
<apeiros_>
yes
<apeiros_>
again, the problem is with the location of the rescue.
<erikh>
I disagree
<erikh>
but meh
<apeiros_>
with what?
<apeiros_>
that the controller is the wrong place to rescue that stuff?
<apeiros_>
note that self.uid = "foo" does not issue a save
<apeiros_>
yeah, that doesn't do a thing
gouthamvel has quit [Ping timeout: 260 seconds]
<erikh>
meh.
<veex>
apeiros_, would you rather go with C# razor views?
<erikh>
the self.save! should work.
<apeiros_>
veex: I'd require a huge payment to even consider touching stuff from m$
<erikh>
C# is nice stuff man
<apeiros_>
erikh: self.save! won't invoke that piece of code
<erikh>
no, right there
<apeiros_>
that rescue will not be hit when you try to save that model
<erikh>
where I do the insert
<erikh>
why not?
<apeiros_>
because in that piece of code, there is no insert
<apeiros_>
the value is only set in the ruby object
<erikh>
meh
<erikh>
stupid rails.
<apeiros_>
the insert is done when you do save/save!. and save/save! does not call that code.
<erikh>
you can't call the save *right there*?
<apeiros_>
yes, you could. it'd be horrible :)
<erikh>
well that's what I've been suggesting this whole time
<apeiros_>
"oh you create a new instance of this model? let me save it to the database right away, no matter whether you actually want that!" :D
<erikh>
bah
gouthamvel has joined #ruby-lang
<apeiros_>
also, since after_initialize is also run after deserializing when reading from the db, it'd mean every select issues an insert too ;-)
* dhoss
wouldn't have a problem with non-lezy saving
<erikh>
I would too
<dhoss>
otherwise i'd put it in a transaction
<erikh>
hrm
<erikh>
that's a really good idea.
<erikh>
transaction, insert, rollback immediately
<apeiros_>
I don't think it'd work out as you think it would
<dhoss>
er it does every time i do it
<apeiros_>
with AR?
<dhoss>
no, so i could be missing something
<apeiros_>
pears & apples then. I'm not arguing that there are other approaches. but with ARs way of modeling things, I doubt that approach could work.
toretore has joined #ruby-lang
<apeiros_>
one of the problems with rails is (IMO) that it shies away from repeating work. i.e. it wants validations only in one place (the model). but that simply leaves soooo many things uncovered and is hiding from reality.
<erikh>
it tries to get rid of the database too much
<erikh>
it's unfortunate.
<apeiros_>
mhm
<erikh>
I understand the rationale, but lord, it's unfortunate.
<apeiros_>
database abstraction is a noble goal. but it's a very leaky abstraction.
<erikh>
I'm starting to play with cassandra more
<erikh>
it's a pretty neat system.
francisfish has quit [Remote host closed the connection]
<symm->
now, why in the world isn't there a File.read('foo', 'r:utf-8') ?
<symm->
the mind boggles
<symm->
I swear to good I look this shit up every time.
<symm->
sorry... wanted to vent
workmad3 has quit [Ping timeout: 252 seconds]
<samuelkadolph>
Because File.read is for simple uses
<lianj>
my ruby reads uf-8 by default
<symm->
... but of course there's a readlines()
<samuelkadolph>
lianj: Only because your terminal locale is UTF8
<lianj>
ofcourse, because thats sane
<symm->
bleh, I am honestly pissed. I know you don't look a gift horse in the mouth, but I wanted to do write a "simple" one off script to do some text stuff, and I've been sitting here trying things out and reading blog posts for 30 minutes
<symm->
to read a fracking utf-8 string from a file.... seriously /me shakes head
<symm->
sorry.. peace out
symm- has left #ruby-lang ["Leaving..."]
<lianj>
o/
<imperator>
time for taco bell
felipe__ has quit [Ping timeout: 246 seconds]
burgestrand has joined #ruby-lang
<rue>
Mm, Taco Bell would be considered great mexican food over here
gouthamvel has joined #ruby-lang
<rue>
Not Chipotle, though. I never understood what people saw in those bland rice bundles.
<rue>
Well, actually, that probably means they’d like it too
neocoin has quit [Remote host closed the connection]
<whitequark>
imperator: for what do you need that?
<whitequark>
not taco bell, but at_exit and CreateRemoteThread.
timepilot has joined #ruby-lang
francisfish has quit [Remote host closed the connection]
<andrewvos>
imperator: Seems the colour codes aren't working for some reason :/
wpaulson has joined #ruby-lang
A124 has joined #ruby-lang
nisstyre has quit [Remote host closed the connection]
<erikh>
imperator: load ansi.sys
<erikh>
or use a proper terminal instead of cmd.exe
zz_chrismcg is now known as chrismcg
<weeb1e>
Is this the best way to split off lines with regex and still retain the remainder of the string? lines = []; while line = s.slice!(/^[^\n]+\n/); lines << line.chomp; end
<imperator>
erikh, tried it with powershell, didn't go well
retro|cz has joined #ruby-lang
<andrewvos>
imperator: I think Console is something that is usable on windows
<imperator>
andrewvos, no luck, though i like the tabbed consoles :)
<andrewvos>
yeah it's a lot better than cmd.exe
<deryl>
hell 4DOS/4NT is better than cmd.exe
<andrewvos>
imperator: Weird that. Trying to remember if there is sort of bash_profile sort of stuff on Windows
<andrewvos>
imperator: Is TERM set to anything?
timepilot has quit [Quit: timepilot]
<erikh>
imperator: yeah, you just need to load up ansi.sys
<erikh>
that should resolve your color issues.
<erikh>
alternatively rdoc might have a thing to turn them off. you should speak with drbrain.
saLOUt has quit [Quit: Konversation terminated!]
<imperator>
andrewvos, no
<imperator>
erikh, just not going to worry about it for now
<imperator>
but thanks
M4g1c5t0rM has joined #ruby-lang
<veex>
I have a problem installing the pg gem on amazon ec2. I've installed the libpg-dev library too and install it using sudo gem install pg with--opt--/usr/lib/ etc
arooni-mobile has quit [Ping timeout: 245 seconds]
saLOUt has joined #ruby-lang
agilobable2 has joined #ruby-lang
agilobable2 has quit [Client Quit]
drollwit has joined #ruby-lang
tbuehlmann has quit []
wpaulson_ has joined #ruby-lang
rippa has quit [Ping timeout: 240 seconds]
drollwit has quit [Remote host closed the connection]
imperator has quit [Quit: Leaving]
sepp2k has joined #ruby-lang
zmack has joined #ruby-lang
drollwit has joined #ruby-lang
sandbags has joined #ruby-lang
sandbags has quit [Changing host]
sandbags has joined #ruby-lang
workmad3 has quit [Ping timeout: 240 seconds]
zmack has quit [Remote host closed the connection]
sepp2k has quit [Ping timeout: 246 seconds]
drollwit has quit [Remote host closed the connection]
perryh is now known as perryh_away
ryanf has joined #ruby-lang
Bwild has quit [Ping timeout: 246 seconds]
zz_wasnotrice is now known as wasnotrice
sepp2k has joined #ruby-lang
wpaulson has quit [Ping timeout: 244 seconds]
<rue>
veex: Sounds exciting
<rue>
A problem, you say.
<erikh>
rue: what, watching arnie blow shit up isn't enough for you? you have to come into irc too?
<erikh>
:P
<rue>
Doing 3 things at once is single-tasking for me.
<erikh>
nerd
<rue>
I’m watching football, Predator, IRCing, and also reading some internet
<rue>
Wife always complains when I switch between two or three shows, but it’s not like you can’t follow along
<erikh>
eh I am very much a single-tasker
<erikh>
I find distractions very easily.
<rue>
Just do so many things that you can’t fit in any distractions
<erikh>
it doesn't work that way for me
<erikh>
there's considerable "spin up" time.
<rue>
You’re not doing many enough things
<erikh>
haha
<erikh>
anyhow, off to the coffee shop.
<erikh>
bbiaw
mssola has quit [Quit: Konversation terminated!]
wpaulson has joined #ruby-lang
qwerxy has quit [Quit: offski]
<apeiros_>
is it possible that $stdin.raw is totally whacko on OSX? (I did a require 'io/console' first…)
<apeiros_>
oh
<rue>
Oh
<apeiros_>
my fault… x is an actually existing command…
<apeiros_>
(in bash)
<apeiros_>
and my little script terminated early :)
francisfish has quit [Remote host closed the connection]
wasnotrice is now known as zz_wasnotrice
fayimora has quit [Ping timeout: 264 seconds]
<apeiros_>
well, it's still whacko. it can deadlock :D
<sandbags>
i'm a little puzzled. I have an array of words with a couple containing accented characters. ary.grep(/[^a-z]/i) picks them out. Yet ary.grep(/[a-z]/i) doesn't exclude them. What am I missing?
<apeiros_>
/[a-z]/i means "must include *one* character which is a-z
<andrewvos>
rue: Explain your tweet please, Sir.
<sandbags>
awww crap, yes
<sandbags>
thanks apeiros_
<apeiros_>
it doesn't mean "the whole string must consist only of characters a-z
<rue>
andrewvos: Which one? There’re quite a few that don’t make sense
<sandbags>
lazy thinking
<andrewvos>
The latest one.
<sandbags>
^ and $ and there we go
<apeiros_>
sandbags: um, no
<apeiros_>
you want \A and \z
<apeiros_>
^ and $ are begin/end of line, not of string.
<sandbags>
apeiros_: /^[a-z]+$/ did the trick
<sandbags>
apeiros_: in this case, same thing
<apeiros_>
*sob*
<apeiros_>
whatever
<sandbags>
apeiros_: quite
gouthamvel has joined #ruby-lang
<rue>
andrewvos: “Football is a game played by 22 players, and in the end, Germany wins”
<apeiros_>
rue: except when switzerland beats them 5:3
<andrewvos>
ahh
<veex>
@rue I've had the problem for a few days nad it's scrapped my install of a few rail clones... I have looked through every stack overflow article about it
<apeiros_>
also, isn't that soccer?
<rue>
veex: Describing the problem would probably help
<rue>
In a gist or something.
<andrewvos>
You just thought you would insert "nad" into that sentence?
<rue>
erikh: I’d always use braces for if/else/while etc. unless it’s literally while(true) blah;
<veex>
The lyrics are timeless. Shakespeare typing.
<erikh>
ah, yeah.
<erikh>
I'll fix that.
<erikh>
dominikh caught a few bugs too, so lots of changes to make.
<erikh>
rue: thank you!
<erikh>
rue: I have a curiosity if you're ok with talking about it -- what do you generally work on? I never hear about it.
<rue>
Nothing right now
seanstickle has joined #ruby-lang
<rue>
P
hinbody has joined #ruby-lang
<rue>
Er. Probably won’t accept anything until August still.
<erikh>
contracting?
perryh_away is now known as perryh
msaffitz has quit [Quit: Computer has gone to sleep.]
<rue>
Yeah, unless something really interesting comes up. There’s this one consulting company here that a couple of the guys keep trying to get me to…they do Scala/Clojure/F# stuff (and also want to expand to Ruby/Python/frontend), so it might be an interesting change
<seanstickle>
Scala/Clojure/ and F#?
<seanstickle>
What a weird mix.
<seanstickle>
I'd have expected Haskell maybe. But not a .Net language.
<erikh>
rue: oh, neat.
<rue>
Haskell, really?
<rue>
Nobody actually does Haskell outside SF and Seattle
<seanstickle>
F# is just a CLRed version of Haskell/ML with less awesomeness.
<rue>
(*Slight exaggeration)
<Mon_Ouie>
F# looks a lot like OCaml
<rue>
seanstickle: The CLR is the important part
<seanstickle>
Or the terrible part, depending on your point of view.
brunocoelho has quit [Remote host closed the connection]
saLOUt has quit [Quit: Konversation terminated!]
<rue>
Well, it’s still important whether good or bad :)
<erikh>
.NET libraries are pretty f'n killer.
workmad3 has joined #ruby-lang
M4g1c5t0rM has joined #ruby-lang
saLOUt has joined #ruby-lang
<seanstickle>
Yes, particularly good on my Mac.
<seanstickle>
Oh wait, no. Maybe I was thinking about my Linux box.
<seanstickle>
Oh wait no.
<seanstickle>
And don't get me started on Mono.
dalekurt_ has joined #ruby-lang
A1241 has joined #ruby-lang
saLOUt has quit [Client Quit]
mistym_ has joined #ruby-lang
Defusal_ has joined #ruby-lang
saLOUt has joined #ruby-lang
workmad3 has quit [Ping timeout: 246 seconds]
Criztian has quit [Remote host closed the connection]
<rue>
Oo, mono is totally great
M4g1c5t0rM has quit [*.net *.split]
A124 has quit [*.net *.split]
mistym has quit [*.net *.split]
yannis has quit [*.net *.split]
outsmartin has quit [*.net *.split]
dalekurt has quit [*.net *.split]
Defusal has quit [*.net *.split]
dalekurt_ is now known as dalekurt
yannis has joined #ruby-lang
Axsuul has quit [Remote host closed the connection]
M4g1c5t0rM has joined #ruby-lang
outsmartin has joined #ruby-lang
heftig has quit [Ping timeout: 272 seconds]
heftig has joined #ruby-lang
heftig has quit [Client Quit]
<rue>
Hrm, didn’t go for the bait.
<seanstickle>
I'm not *that* crazy
cantonic has joined #ruby-lang
vesan_ has joined #ruby-lang
<apeiros_>
hm, \e[0J is bad to clear the screen :-S
vesan has quit [Read error: Connection reset by peer]