Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder
For anyone else learning rust, this code review of ripgrep is really fantastic: http://blog.mbrt.it/2016-12-01-ripgrep-code-review/

Adbot
ADBOT LOVES YOU

Bloody
Mar 3, 2013

There's also the underhanded c++ contest which is cute

VikingofRock
Aug 24, 2008




Bloody posted:

There's also the underhanded c++ contest which is cute

Wait really? I had only ever seen underhanded C (which owns).

CPColin
Sep 9, 2003

Big ol' smile.
I used a named break in Java this week at work. :getin:

Bored Online
May 25, 2009

We don't need Rome telling us what to do.
what is the current hipster reference to learn python with or does it even matter

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

Dongslayer. posted:

what is the current hipster reference to learn python with or does it even matter

there's one but you've probably never heard of it

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde

MALE SHOEGAZE posted:

there's one but you've probably never heard of it

triple sulk
Sep 17, 2014



MALE SHOEGAZE posted:

there's one but you've probably never heard of it

BobHoward
Feb 13, 2012

The only thing white people deserve is a bullet to their empty skull

Dongslayer. posted:

what is the current hipster reference to learn python with or does it even matter

googling for poo poo has worked pretty well for me tbh

python irritates me. i've been learning it, and despite idiotic things like semantic whitespace, overall it started feeling like a nice perl replacement. was even finding that despite all the ludicrous compactness tricks in perl, i was using fewer lines of code in python, and it was like 1000x more readable.

then [needle drop] i port a simple perl script that reads files and regexes each line and discover that python only manages about 1/10th the throughput

how do they do that. i refuse to believe perl's implementation is anything other than a garbage fire to match the externally visible plang i've been using for years, so how hard can it be to match its performance

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
perl is generally extremely good at string processing and specifically has a fantastic regexp implementation

iirc perl's implementation is overall quite good, especially for something that hasn't had the same effort put into it as javascript. javascript regexp implementations are also generally superior, btw

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord
try compiling the regex objects, it used to help a lot with the performance

and use the ASCII flag if you're not dealing with unicode

skimothy milkerson
Nov 19, 2006

CPColin posted:

I used a named break in Java this week at work. :getin:

Was it to break out all the way out of a loop/switch statement inside another loop? It feels so dirty.

"I'll take Refactoring for 600."

comedyblissoption
Mar 15, 2006

python 3 used utf-32 encoding instead of utf-8 so everything is going to be unnecessarily slower

edit: apparently it's a lot more complicated than that with later versions of python 3
http://stackoverflow.com/a/9079985

comedyblissoption fucked around with this message at 06:34 on Dec 11, 2016

CPColin
Sep 9, 2003

Big ol' smile.

Skim Milk posted:

Was it to break out all the way out of a loop/switch statement inside another loop? It feels so dirty.

"I'll take Refactoring for 600."

That's the one! It's actually a named continue, now that I look at it again. Wouldn't have had to do it, if Java had for-else.

Sapozhnik
Jan 2, 2005

Nap Ghost

CPColin posted:

That's the one! It's actually a named continue, now that I look at it again. Wouldn't have had to do it, if Java had for-else.

isn't that the thing they had to remove from some other language because almost nobody understood what that hosed up construct actually does

CPColin
Sep 9, 2003

Big ol' smile.
Possibly. It could use a better keyword than "else," certainly. Maybe for-didn'tbreak?

redleader
Aug 18, 2005

Engage according to operational parameters
what we really need is a more thorough set of constructs for working with loops:
code:

for (...) {
}
finally {
    // run if loop runs to completion
}
catch {
    // run if break used to exit loop 
}
else {
    // run if loop never entered
}

of course, we're reusing existing keywords for maximum backwards compatibility (and confusion)

BobHoward
Feb 13, 2012

The only thing white people deserve is a bullet to their empty skull

rjmccall posted:

perl is generally extremely good at string processing and specifically has a fantastic regexp implementation

iirc perl's implementation is overall quite good, especially for something that hasn't had the same effort put into it as javascript. javascript regexp implementations are also generally superior, btw

huh. well count me surprised (not at js, though)

Symbolic Butt posted:

try compiling the regex objects, it used to help a lot with the performance

and use the ASCII flag if you're not dealing with unicode

comedyblissoption posted:

python 3 used utf-32 encoding instead of utf-8 so everything is going to be unnecessarily slower

edit: apparently it's a lot more complicated than that with later versions of python 3
http://stackoverflow.com/a/9079985

will look into these things. annoying if it turns out you have to jump through extra hoops to get on the performance path

Gul Banana
Nov 28, 2003

python is also just really slow overall. for some reason people go to the effort of writing C extensions to do things fast in it

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

redleader posted:

what we really need is a more thorough set of constructs for working with loops:
code:

for (...) {
}
finally {
    // run if loop runs to completion
}
catch {
    // run if break used to exit loop 
}
else {
    // run if loop never entered
}

of course, we're reusing existing keywords for maximum backwards compatibility (and confusion)

why are you using a for loop anyway? just map a function across your collection

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Sapozhnik posted:

isn't that the thing they had to remove from some other language because almost nobody understood what that hosed up construct actually does

there was a proposal to add it to c++ which was withdrawn when it was pointed out that despite citing python as the inspiration for it, it was proposing the opposite of what python has

redleader
Aug 18, 2005

Engage according to operational parameters

leper khan posted:

why are you using a for loop anyway? just map a function across your collection

no. that makes it too easy to reason about the code. by reusing a bunch of keywords, we can significantly increase the difficulty of comprehension - especially if we introduce some subtle and surprising semantics here

CPColin
Sep 9, 2003

Big ol' smile.

leper khan posted:

why are you using a for loop anyway? just map a function across your collection

My for loop had side effects!

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde
once while browsing old issues of CACM (i don;t remember why) i happened on this really weird article in a 1970s/early 1980s issue, which i don't think was an april issue, where the author had rolled while loops, until loops, and i think a couple of other control structures into one, and there was really nothing to the article except "look, I could do this!" and for some reason CACM published it

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde
(and that author's name was larry wall)

VikingofRock
Aug 24, 2008




Gazpacho posted:

once while browsing old issues of CACM (i don;t remember why) i happened on this really weird article in a 1970s/early 1980s issue, which i don't think was an april issue, where the author had rolled while loops, until loops, and i think a couple of other control structures into one, and there was really nothing to the article except "look, I could do this!" and for some reason CACM published it

personally i just use if and goto for better performance and more fine-grained control. it's very expressive

crazysim
May 23, 2004
I AM SOOOOO GAY

Symbolic Butt posted:

try compiling the regex objects, it used to help a lot with the performance

and use the ASCII flag if you're not dealing with unicode

i think the python regex compiler cache globally. could be wrong though.

Xarn
Jun 26, 2015

crazysim posted:

i think the python regex compiler cache globally. could be wrong though.

Its supposed to, but there is still speed-up from compilation :shrug:.

HappyHippo
Nov 19, 2003
Do you have an Air Miles Card?
i didn't realize that java had a named break, that's pretty neat. that's basically the only situation where i use gotos.

gonadic io
Feb 16, 2011

>>=

HappyHippo posted:

i didn't realize that java had a named break, that's pretty neat. that's basically the only situation where i use gotos.

rust has it too :q:

i used it the other day when looping through events in my game loop. user pressed Q? exit out of the main loop

e: now though I just moved it out into its own function and return early instead of breaking early.

Soricidus
Oct 21, 2010
freedom-hating statist shill

Xarn posted:

Its supposed to, but there is still speed-up from compilation :shrug:.

that's not so surprising if the cache just does a hash lookup on the regex string, which is going to have a hit if it's in a tight inner loop that won't be there for the compiled object.

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

Soricidus posted:

that's not so surprising if the cache just does a hash lookup on the regex string, which is going to have a hit if it's in a tight inner loop that won't be there for the compiled object.

It also helps pin things in the caches that might otherwise fall out from use of libraries which also use regular expressions.

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
back to our homemade variant! well, we started in the completely wrong way, apparently. we want feature parity with std::variant (minus the boring parts), and an std::variant that can only contain literal types is, in turn a literal type. a literal, or constexpr type is a type that acts like a literal (like say, a number literal or a string literal), and can be used wherever literals can, like array sizes, template parameters, static_assert and so on. of course, a literal type is subject to a ton of constraints, that essentially boil down to "predictable compilation times" and "no runtime environment". the former is obvious (you don't want the whole program to run at compile time, although you'd hardly call c++ compilation times "predictable") and the latter is necessary: the runtime environment (and by extension, constexpr code) the compiler runs in is neither safe to use (unless compiler writers start listening to reason, i.e. me, and run the compile-time code in a proper process that I can debug) nor necessarily matches the runtime environment expected by the program. one of the things that can't be done in literals is aliasing, i.e. taking an area of memory of one type and treating it as a different type: the whole concept of "area of memory" is runtime environment nonsense that the compiler won't entertain

remember how I decided to base my variant around aligned_union? aligned_union is a generic type that acts like an untyped, uninitialized union that can contain any of a list of types: it's large enough and memory-aligned enough to be safely cast to any of the specified types, and so it may sound perfect as the basis of variant. unlike real unions, though, aligned_union requires type casts, and type casts imply aliasing, and aliasing is inaccessible in literal expressions. real unions work perfectly in literal expressions, but they are lists of named fields, and as we've seen at the beginning of this Learning Experience, one very important thing template code can't do is define names. what templates can do perfectly well, however, is list manipulation through recursion. if, in an ideal world, we'd pass a template a list of types and names, and get it to generate a union like this:
C++ code:
union {
	Type1 field1;
	Type2 field2;
	// ...
	TypeN fieldN;
};
in this imperfect world where beyonce won't see the error of her ways and dump uggo jay z for a hot european rockstar c++ programmer, we'll have to make do with:
C++ code:
union {
	Type1 head;
	union {
		Type2 head;
		union {
			// ...
			TypeN head;
		} tail;
	} tail;
};
which is not only doable but downright trivial with templates (in a real world library we'd attempt to reduce the depth of recursion - a limited resource that ultimately belongs to the programmer - by matching more than one "head" element at once, but we're operating on the principle of gently caress It and we won't). first we start with the prototype:
C++ code:
template<class... Types>
union either_storage;
// reminder that I've chosen to name my variant "either"
then we handle the recursive case:
C++ code:
template<class Head, class... Tail>
union either_storage<Head, Tail...> {
	Head head;
	either_storage<Tail...> tail;
};
and finally, the fixed point:
C++ code:
template<class... Types>
union either_storage {
	static_assert(sizeof...(Types) == 0, "Expected empty type list");
};
note that, since an empty list is legal (empty unions are perfectly legal), we can handle the fixed point as the general case, and the recursion in a specialization. this isn't the only way to do it: we may have implemented both cases as specializations, but then you have nothing that proves that your specializations exhaustively handle all cases. it's ultimately a matter of preference (unless, and this is very likely, there's a good reason to pick an approach over the other, that I can't think of yet)

you may wonder, can a union contain types with non-trivial constructors and destructors? and how, exactly, does the compiler know which field of the union is the active one? these are really good questions! in fact, before c++11, unions could only contain trivial types. the limitations were greatly relaxed, specifically to allow tagged unions. the full ruleset is not important right now, but two important rules are: if any of the fields of the union have a non-trivial default constructor, the union has no default constructor; same goes for the destructor. the default constructor is not terribly important: all our variant class needs from this base component is a generic constructor that takes an index to the field to be constructed, and a list of arguments to be passed to the constructor of the field. something like this:
C++ code:
// just like the indices template I introduced last time, this template simply
// acts as a compile-time container. using template parameters as items in a
// container gives us a collection that can be pattern-matched
template<std::size_t>
struct in_place_index_t {};

// instances of in_place_index_t will be used as tags in tag dispatching. as a
// shortcut for "in_place_index_t<N>{}", we define this template variable:
template<std::size_t I>
constexpr in_place_index_t<I> in_place_index;
// the programmer can now use "in_place_index<N>" instead

template<class... Types>
union either_storage {
	static_assert(sizeof...(Types) == 0, "Expected empty type list");

	// the empty union recognizes the positional constructor but rejects it as
	// bourgeois heterodoxy
	template<std::size_t I, class... Args>
	explicit constexpr either_storage(in_place_index_t<I>, Args&&...) = delete;
};

template<class Head, class... Tail>
union either_storage<Head, Tail...> {
	Head head;
	either_storage<Tail...> tail;

	// if the index is 0, construct the head of the list
	template<class... Types>
	explicit constexpr either_storage(in_place_index_t<0>, Args&&... args):
		head(std::forward<Args>(args)...)
	{}

	// the constructor is marked explicit, so that it doesn't count as a "convert
	// from" operator that implicitly converts any in_place_index_t into any
	// given either_storage (that would be bad). it's also marked constexpr, so
	// that if the constructor of Head is, in turn, constexpr, it will be constexpr
	// too, making this specialization of either_storage a literal

	// otherwise, recurse on the tail
	template<std::size_t I, class... Types>
	explicit constexpr either_storage(in_place_index_t<I>, Args&&... args):
		tail(in_place_index<I - 1>, std::forward<Args>(args)...)
	{}

	// pattern matching is different and inconsistent between templates, functions
	// and template functions, and I can never quite remember all the rules. I'm
	// pretty sure that the above is unambiguous and will work fine, though
};
well, we solved one issue, namely constructing the desired type in a list of types. remember the other important rule for unions? if any of the contained types has a non-trivial destructor, the union won't have a destructor, and we'll have to specify one explicitly. it's no biggie, as a humble storage class, all it needs is an empty destructor: it will be the variant that owns the storage object to destroy the currently active type, explicitly. but there's one problem: an explicit destructor, even an empty one, is considered nontrivial, and a nontrivial destructor means the type is no longer a literal... c++: if it seems easy, it's wrong. we'll need two storage types: one for trivially-destructible types only, that can be used in a literal expression, and one that may contain non-trivially-destructible types, for everywhere else. next time we'll see how to make it... well, no, I'm not going to sugarcoat it, we can't make it painless. it will be the tip of an iceberg of suck, but the payoff will be worth it (if you're the kind of person who cares about making complex classes constexpr-compliant! which I apparently am)

Slurps Mad Rips
Jan 25, 2009

Bwaltow!

hackbunny posted:

the start of a variant hole you will never escape from

it would be easier to implement the union end case with a single item

C++ code:
template <class...> union either_storage;
template <class Head, class... Tails>
union either_storage<Head, Tails...> {
  Head value;
  either_storage<Tails...> other;
};
template <class Head>
union either_storage<Head> {
	Head value;
};
also std::variant just landed in libc++, and there's some cool stuff in there i wouldn't have thought of

Max Facetime
Apr 18, 2009

GLSL is a wonderful language of simple, predictable features with many, many high quality cross-platform compilers and

C++ code:
				bool test = (y- s1)/ pixel>= 1.;
//				float testN = float(!test);
//				float testY = float(test);
				if(!test== test) {
					debugColor1 = vec4(1,0,0,1);
				} else {
					debugColor1 = vec4(0,0,0,1);
				}
can generate

Only registered members can see post attachments!

JawnV6
Jul 4, 2004

So hot ...
is that from the folks fuzzing it?

e: here's one of their articles

Max Facetime
Apr 18, 2009

JawnV6 posted:

is that from the folks fuzzing it?

e: here's one of their articles

no, it's something I ran into just moments ago on desktop. i'm running on opengl 4.40 compatibility profile and whichever NVidia's driver windows update has installed (21.21.13.6909, published 2016-08-01 looks like it)

I think I might have an infinite value that somehow survives being coerced into a Boolean and :duckie: ...time to go to bed

thanks for the article, i'll have to dig into it

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Slurps Mad Rips posted:

hackbunny posted:

the start of a variant hole you will never escape from

joke's on you! it's already done and I'm doing a postmortem. last week I had five days off and I used them well

Slurps Mad Rips posted:

it would be easier to implement the union end case with a single item

I do this in my actual for real implementation, but for my posts I rewrite the code from memory. this way I can often understand the code better than when I wrote it, and sometimes have new ideas

Slurps Mad Rips posted:

also std::variant just landed in libc++, and there's some cool stuff in there i wouldn't have thought of

do tell, by now I may even understand

Xarn
Jun 26, 2015

hackbunny posted:

we'll need two storage types: one for trivially-destructible types only, that can be used in a literal expression, and one that may contain non-trivially-destructible types, for everywhere else. next time we'll see how to make it... well, no, I'm not going to sugarcoat it, we can't make it painless. it will be the tip of an iceberg of suck, but the payoff will be worth it (if you're the kind of person who cares about making complex classes constexpr-compliant! which I apparently am)

This is C++ telling you to stop trying to constexpresize the variant, please listen to it. :v:

(I have had to deal with something similar, albeit with lot less recursive templates, and I am still not sure it was worth it)

Adbot
ADBOT LOVES YOU

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

Xarn posted:

This is C++ telling you to stop trying to constexpresize the variant, please listen to it. :v:

too late! I already have lines like these:
C++ code:
static_assert(get<long>(either<int, long, double>(in_place_index<1>, 10)) == 10);
static_assert(visit([](auto v) { return v; }, either<int, long, double>(in_place_index<2>, 1.0)) == 1);
(constexpr compliance wasn't even the hardest part!)

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply