{% extends "_post.html" %}
{% hyde
title: "The Caves of Clojure: Interlude 1"
snip: "Black magic."
created: 2012-07-14 17:06:00
flattr: true
%}
{% block article %}
This post is part of an ongoing series. If you haven't already done so, you
should probably start at [the beginning][].
This entry is an interlude after [post five in Trystan's tutorial][trystan-tut].
If you want to follow along, the code for the series is [on Bitbucket][bb] and
[on GitHub][gh]. Update to the `interlude-1` tag to see the code as it stands
after this post.
[the beginning]: /blog/2012/07/caves-of-clojure-01/
[trystan-tut]: http://trystans.blogspot.com/2011/09/roguelike-tutorial-05-stationary.html
[bb]: http://bitbucket.org/sjl/caves/
[gh]: http://github.com/sjl/caves/
[TOC]
Summary
-------
At the end of the last post I said that this one would be about refactoring and
a macro, so that's what it's going to be.
Refactoring
-----------
I don't want to bore you with lots of long chunks of refactored code, so I'll
just outline the changes and if you want to see what happened you can look in
the repo on GitHub.
I ran [Kibit][] over the code and fixed what it complained.
[jdmarble][] on GitHub pointed out a place where I was using `update-in` and
could simplify it to `assoc-in`. This is the kind of thing Kibit should catch,
so I added it in and sent a pull request.
[jmgimeno][] on GitHub pointed out that I could use an `atom` for the entity ID
generation instead of a `ref`. That cleaned up a few lines nicely.
I updated the game loop and moved the call to `draw-game` so it doesn't get draw
more times than is necessary.
I added a bunch of comments and docstrings throughout the code.
I added a few functions to the latest release of [clojure-lanterna][] that
allowed me to clean up the UI drawing code. I was able to completely remove the
`clear-screen` function, and replaced the hardcoded screen size with a dymanic
lookup.
I also changed how the actual screen gets drawn. Look in the repo for the full
details -- I think it's much nicer now (though I'm still not 100% happy).
I think that's about it. On to the meat of this post.
[kibit]: https://github.com/jonase/kibit/
[jdmarble]: https://github.com/jdmarble
[jmgimeno]: https://github.com/jmgimeno
[clojure-lanterna]: http://sjl.bitbucket.org/clojure-lanterna/
The Problem
-----------
Right now, the entity system in the Caves works like this:
* Aspects are Clojure protocols. They define what functions an entity must
implement to have that aspect.
* Entity types use `extend-type` to add the appropriate implementations for the
aspects they want to be.
This is all vanilla Clojure, and up until now it's been fine because there was
no crossover between the `Lichen` aspects and the `Player` aspects. But what's
going to happen when I create a creature that shares behavior with one or both
of them?
To see the problem, I'm going to create a `Bunny` entity that will hop around
the screen, and can also be destroyed (assuming the player is a terrible,
terrible person). So I'll create `entities/bunny.clj`:
:::clojure
(ns caves.entities.bunny)
(defrecord Bunny [id glyph color location hp])
(extend-type Bunny Entity
(tick [this world]
world))
We'll worry about `tick` soon, but so far, so good. Now I need to let bunnies
move around:
:::clojure
(extend-type Bunny Mobile
(move [this world dest]
{:pre [(can-move? this world dest)]}
(assoc-in world [:entities (:id this) :location] dest))
(can-move? [this world dest]
(is-empty? world dest)))
Hmm, where have we seen this code before?
It's an almost exact copy of the `Player`'s implementation of the `Mobile`
protocol!
When you think about it, this makes sense. Most of the entities in the game
will have the same implementation for most aspects. The flexibility of Clojure
protocols means I have the power to customize behavior for every one of them,
but it also means that I have to redefine the same behavior over and over.
Or do I?
The Not-Quite Solutions
-----------------------
There are a number of ways I could try to get around this duplication.
First, I could define the "default" implementations as separate, normal
functions, and then the entity-specific implementations could just call those.
This would work, absolutely. It would isolate the generic functionality in one
place successfully. But it means I'd have to manually type out the calls to
those generic functions all the time. This is a Lisp -- I can do better.
The next idea is to make `Object` implement every aspect (with the default
implementations). This isn't ideal for two reasons.
First, it means that the type of an entity is no longer useful. If `Object`
implements `Mobile` to provide the default functionality, it means *every*
entity will effectively be `Mobile` even if it shouldn't be!
Second, it doesn't even give me everything I want. Observe:
:::clojure
(defprotocol Foo
(hello [this])
(world [this]))
(defrecord A [])
(extend-type Object Foo
(hello [this] :hello-object)
(world [this] :world-object))
(extend-type A Foo
(hello [this] :hello-a))
(def a (->A))
(hello a) ; Works
(world a) ; Doesn't work
In this example, the `Foo` object doesn't get the benefit of the default
implementation because it implements the protocol itself. So when figuring out
what `world` function to call Clojure asks "Hmm, does A implement Foo? Oh, it
does? Okay, I'll use A's implementations then".
So the entities would either have to implement all of the aspect functions
(resulting in the duplication of the ones they don't need to change) or none of
them (which *would* give them the defaults).
So this isn't ideal. I could also have used multimethods here, because they
*do* support default implementations. But multimethods don't give me a nice
way to group related functions together like protocols.
Protocols also interact with the type system to give me handy functionality
like:
:::clojure
(defn find-targets
"Find potential things to kill!"
[world]
(filter #(satisfies? Destructible %)
(vals (:entities world))))
The concept of "bunnies are destructible" is a useful one, and I'd lose it if
I used multimethods.
The Macro
---------
Macros are not something you should reach for right away. They're tricky and
much harder to understand than a normal function. But when all else fails,
they're there as a last resort.
I couldn't figure out a way to do this without macros, so it's time to roll up
my sleeves and work some dark Lispy magic to get a nice syntax.
When I'm writing a macro, my first step is usually to start at the end by
writing out what I want its ultimate usage to be. For this functionality I'm
actually going to need a pair of macros.
First, `defaspect` will replace `defprotocol` and allow me to define a protocol
*and* provide the default implementations:
:::clojure
(defaspect Mobile
(move [this world dest]
{:pre [(can-move? this world dest)]}
(assoc-in world [:entities (:id this) :location] dest))
(can-move? [this world dest]
(is-empty? world dest)))
Those implementations are generic enough (moving moves an entity from their
current space into an empty one) that many entities will probably be able to use
them unchanged.
I'll also need a macro to replace `extend-type`. I decided to call it
`add-aspect`:
:::clojure
(add-aspect EarthElemental Mobile
(can-move? [this world]
(entity-at? world dest)))
In this example the `EarthElemental` entity is implementing `Mobile`. It will
use the default `move` implementation (which just changes its location), but it
overrides `can-move?`. Earth elementals can't walk through other entities, but
they *can* walk through the rock walls of the Caves.
So I've got my examples of usage, now it's time to implement the macros. I'll
start with `defaspect`.
My second step when writing a macro is writing out what the usage should be
expanded into. After a bit of thinking I came up with this:
:::clojure
(defaspect Mobile
(move [this world dest]
{:pre [(can-move? this world dest)]}
(assoc-in world [:entities (:id this) :location] dest))
(can-move? [this world dest]
(is-empty? world dest)))
; should expand into
(do
(defprotocol Mobile
(move [this world dest])
(can-move? [this world dest]))
(def Mobile
(with-meta Mobile
{:defaults
{:move (fn [this world dest]
{:pre [(can-move? this world dest)]}
(assoc-in world [:entities (:id this) :location] dest))
:can-move? (fn [this world dest]
(is-empty? world dest))}})))
This looks a bit complicated because of the method implementations, which aren't
really important when writing the macro, so let's remove those:
:::clojure
(defaspect Mobile
(move [this world dest]
{:pre [(can-move? this world dest)]}
(assoc-in world [:entities (:id this) :location] dest))
(can-move? [this world dest]
(is-empty? world dest)))
; should expand into
(do
(defprotocol Mobile
(move [this world dest])
(can-move? [this world dest]))
(def Mobile
(with-meta Mobile
{:defaults
{:move (fn [this world dest] ...)
:can-move? (fn [this world dest] ...)}})))
That's a bit easier to read. The `defaspect` macro is going to take all the
forms I give it and expand into a `do` form with two actions: defining the
protocol as before, and attaching a map to the Protocol itself with Clojure's
metadata feature.
This map will contain the default implementations. For now just trust me that
I'm going to need them in a map later.
Now to write the actual macro! It'll go in `entities/core.clj` for the moment.
I'll start with a skeleton:
:::clojure
(defmacro defaspect [label & fns]
(let [fnmap (make-fnmap fns)
fnheads (make-fnheads fns)]
`(do
(defprotocol ~label
~@fnheads)
(def ~label
(with-meta ~label {:defaults ~fnmap})))))
If you've used macros before, this should be pretty easy to read. I've pulled
as much functionality as possible into two helper functions. Let's look at
those:
:::clojure
(defn make-fnmap
"Make a function map out of the given sequence of fnspecs.
A function map is a map of functions that you'd pass to extend. For example,
this sequence of fnspecs:
((foo [a] (println a)
(bar [a b] (+ a b)))
Would be turned into this fnmap:
{:foo (fn [a] (println a))
:bar (fn [a b] (+ a b))}
"
[fns]
(into {} (for [[label fntail] (map (juxt first rest) fns)]
[(keyword label)
`(fn ~@fntail)])))
(defn make-fnheads
"Make a sequence of fnheads of of the given sequence of fnspecs.
A fnhead is a sequence of (name args) like you'd pass to defprotocol. For
example, this sequence of fnspecs:
((foo [a] (println a))
(bar [a b] (+ a b)))
Would be turned into this sequence of fnheads:
((foo [a])
(bar [a b]))
"
[fns]
(map #(take 2 %) fns))
Hopefully the docstrings will make them pretty clear. If you have questions let
me know (or play around with them in a REPL to see how they behave).
And with that, `defaspect` is complete! I now have a way to define a protocol
and attach some default implementations to it in one easy, beautiful call.
The other macro, `add-aspect`, is a piece of cake now that I've got the helper
functions:
:::clojure
(defmacro add-aspect [entity aspect & fns]
(let [fnmap (make-fnmap fns)]
`(extend ~entity ~aspect (merge (:defaults (meta ~aspect))
~fnmap))))
The important thing in understanding this macro is `extend`. `extend` is what
`extend-type` and `extend-protocol` sugar over. It takes a type, a protocol,
and a map of the implementations of that protocol's functions.
The key word there is "map", which really does mean a plain old Clojure map. So
this macro will expand like so:
:::clojure
(add-aspect EarthElemental Mobile
(can-move? [this world dest]
(entity-at? world dest)))
; should expand into
(extend EarthElemental Mobile
(merge (:defaults (meta Mobile))
{:can-move? (fn [this world dest] ...)})
The `(:defaults (meta Mobile))` simply retrieves the function mapping that
`defaspect` attached to the Protocol, so in effect I get something like:
:::clojure
(extend EarthElemental Mobile
(merge {:move (fn [this world dest] ...)
:can-move? (fn [this world dest] ...)}
{:can-move? (fn [this world dest] ...)})
`merge` is just the vanilla Clojure `merge` function, so the resulting map will
have the default implementations overridden by any custom ones given.
And that's it! Let's see it in action.
Usage
-----
First I need to update the aspects to use `defaspect` and include their default
implementations. Here's `Destructible`:
:::clojure
(ns caves.entities.aspects.destructible
(:use [caves.entities.core :only [defaspect]]))
(defaspect Destructible
(take-damage [{:keys [id] :as this} world damage]
(let [damaged-this (update-in this [:hp] - damage)]
(if-not (pos? (:hp damaged-this))
(update-in world [:entities] dissoc id)
(assoc-in world [:entities id] damaged-this)))))
The code is just torn out of the `Lichen` code. Since this is how lichens will
act, I can update them to use `add-aspect`:
:::clojure
(add-aspect Lichen Destructible)
One line! Nice.
I'll make bunnies destructible too:
:::clojure
(add-aspect Bunny Destructible)
Perfect. I then updated `Mobile` to use the `defaspect` macro. Look in the
repository if you want to see that. Now players and bunnies can both use the
same default implementations for movement:
:::clojure
(add-aspect Bunny Mobile)
(add-aspect Player Mobile)
Beautiful. I then converted the remaining aspects and implementations to use
these macros.
Let's add some bunnies to the world. First I'll need a `make-bunny` function
similar to `make-lichen`:
:::clojure
(defn make-bunny [location]
(->Bunny (get-id) "v" :yellow location 1))
I don't know why I picked yellow. Are there yellow bunnies? There are in
*this* world. I used a `v` as the glyph because it kind of looks like bunny
ears.
Then I updated the world-populating code over in `input.clj`:
:::clojure
(defn add-creature [world make-creature]
(let [creature (make-creature (find-empty-tile world))]
(assoc-in world [:entities (:id creature)] creature)))
(defn add-creatures [world make-creature n]
(nth (iterate #(add-creature % make-creature)
world)
n))
(defn populate-world [world]
(let [world (assoc-in world [:entities :player]
(make-player (find-empty-tile world)))]
(-> world
(add-creatures make-lichen 30)
(add-creatures make-bunny 20))))
Bunnies will be a bit rarer than lichens for the moment (and maybe in the future
they could eat them).
Finally, let's run the game!
![Screenshot](/media/images{{ parent_url }}/caves-interlude-1-01.png)
Bunnies! They're populated into the world and the player can kill them because
they're `Destructible`.
Right now they *can* move, but choose not to. I'll fix that by updating their
`tick` function:
:::clojure
(extend-type Bunny Entity
(tick [this world]
(if-let [target (find-empty-neighbor world (:location this))]
(move this world target)
world)))
Now they'll move whenever they're not backed into a corner. Obviously move
complicated AI is possible, but this is fine for now.
So this is all good, but I haven't even used the "override one function of an
aspect but not others" part of my fancy macro. I'll add another creature to
show that off:
:::clojure
(ns caves.entities.silverfish
(:use [caves.entities.core :only [Entity get-id add-aspect]]
[caves.entities.aspects.destructible :only [Destructible]]
[caves.entities.aspects.mobile :only [Mobile move can-move?]]
[caves.world :only [get-entity-at]]
[caves.coords :only [neighbors]]))
(defrecord Silverfish [id glyph color location hp])
(defn make-silverfish [location]
(->Silverfish (get-id) "~" :white location 1))
(extend-type Silverfish Entity
(tick [this world]
(let [target (rand-nth (neighbors (:location this)))]
(if (get-entity-at world target)
world
(move this world target)))))
(add-aspect Silverfish Mobile
(can-move? [this world dest]
(not (get-entity-at world dest))))
(add-aspect Silverfish Destructible)
Oh no! The horrible silverfish from Minecraft! They wormy little guys are
`Mobile` and `Destructible`, but they can move through walls with their custom
`can-move?` function.
Notice how I didn't have to provide an implementation of `move`. Silverfish
move like any other mobile entity (just by updating their location), the only
thing special is where they can go.
After adding them to the world population, we can see a few wriggling their way
though the walls in the northeast corner:
![Screenshot](/media/images{{ parent_url }}/caves-interlude-1-02.png)
Results
-------
You can view the code [on GitHub][result-code] if you want to see the end
result.
[result-code]: https://github.com/sjl/caves/tree/interlude-1/src/caves
These two macros allowed me to add a new mob, with custom movement, in about 13
lines of code (excluding imports). That's pretty nice! They certainly aren't
perfect though.
For one, every aspect *has* to define default implementations for its methods.
You can't force all entities to implement it. This isn't a big deal for now,
but I may want to add it in later.
Second, it doesn't handle docstrings properly. Again, not a huge problem at the
moment but something to put on the todo list for later.
Finally, defining the protocol and implementations in the same form may lead to
some tricky circular import issues. I can always split them into separate files
in the future though.
That about wraps it up. If you have any questions or comments let me know! In
the next entry I'll get back to Trystan's tutorial.
{% endblock article %}


How To Build A garden Plan
Lorem Ipsum is simply dummy text of the printing and typesetting industry has been the industry's standard dummy text ever since the been when an unknown printer...
How To Build A garden Plan
Lorem Ipsum is simply dummy text of the printing and typesetting industry has been the industry's standard dummy text ever since the been when an unknown printer...
How To Build A garden Plan
Lorem Ipsum is simply dummy text of the printing and typesetting industry has been the industry's standard dummy text ever since the been when an unknown printer...


Redis
class Redis (View source)
Methods
Create a new Redis instance. If passed sufficient information in the options array it is also possible to connect to an instance at the same time.
No description
Compress a value with the currently configured compressor as set with Redis::setOption().
Uncompress the provided argument that has been compressed with the currently configured compressor as set with Redis::setOption().
Prefix the passed argument with the currently set key prefix as set with Redis::setOption().
Serialize the provided value with the currently set serializer as set with Redis::setOption().
Unserialize the passed argument with the currently set serializer as set with Redis::setOption().
Pack the provided value with the configured serializer and compressor as set with Redis::setOption().
Unpack the provided value with the configured compressor and serializer as set with Redis::setOption().
No description
Append data to a Redis STRING key.
Authenticate a Redis connection after its been established.
Execute a save of the Redis database in the background.
Asynchronously rewrite Redis' append-only file
Count the number of set bits in a Redis string.
No description
Return the position of the first bit set to 0 or 1 in a string.
Pop an element off the beginning of a Redis list or lists, potentially blocking up to a specified timeout. This method may be called in two distinct ways, of which examples are provided below.
Pop an element off of the end of a Redis list or lists, potentially blocking up to a specified timeout.
Pop an element from the end of a Redis list, pushing it to the beginning of another Redis list, optionally blocking up to a specified timeout.
POP the maximum scoring element off of one or more sorted sets, blocking up to a specified timeout if no elements are available.
POP the minimum scoring element off of one or more sorted sets, blocking up to a specified timeout if no elements are available
POP one or more elements from one or more sorted sets, blocking up to a specified amount of time when no elements are available.
POP one or more of the highest or lowest scoring elements from one or more sorted sets.
Pop one or more elements from one or more Redis LISTs, blocking up to a specified timeout when no elements are available.
Pop one or more elements off of one or more Redis LISTs.
Reset any last error on the connection to NULL
No description
No description
No description
Execute the Redis CONFIG command in a variety of ways.
No description
Make a copy of a key.
Return the number of keys in the currently selected Redis database.
No description
Decrement a Redis integer by 1 or a provided value.
Decrement a redis integer by a value
Delete one or more keys from Redis.
Discard a transaction currently in progress.
Dump Redis' internal binary representation of a key.
Have Redis repeat back an arbitrary string to the client.
Execute a LUA script on the redis server.
This is simply the read-only variant of eval, meaning the underlying script may not modify data in redis.
Execute a LUA script on the server but instead of sending the script, send the SHA1 hash of the script.
This is simply the read-only variant of evalsha, meaning the underlying script may not modify data in redis.
Execute either a MULTI or PIPELINE block and return the array of replies.
Test if one or more keys exist.
Sets an expiration in seconds on the key in question. If connected to redis-server >= 7.0.0 you may send an additional "mode" argument which modifies how the command will execute.
Set a key to expire at an exact unix timestamp.
No description
Get the expiration of a given key as a unix timestamp
Get the expriation timestamp of a given Redis key but in milliseconds.
Deletes every key in all Redis databases
Deletes all the keys of the currently selected database.
Add one or more members to a geospacial sorted set
Get the distance between two members of a geospacially encoded sorted set.
Retrieve one or more GeoHash encoded strings for members of the set.
Return the longitude and lattitude for one or more members of a geospacially encoded sorted set.
Retrieve members of a geospacially sorted set that are within a certain radius of a location.
A readonly variant of GEORADIUS
that may be executed on replicas.
Similar to GEORADIUS
except it uses a member as the center of the query.
This is the read-only variant of GEORADIUSBYMEMBER
that can be run on replicas.
Search a geospacial sorted set for members in various ways.
Search a geospacial sorted set for members within a given area or range, storing the results into a new set.
Retrieve a string keys value.
Get the authentication information on the connection, if any.
Get the bit at a given index in a string key.
Get the value of a key and optionally set it's expiration.
Get the database number PhpRedis thinks we're connected to.
Get a key from Redis and delete it in an atomic operation.
Return the host or Unix socket we are connected to.
Get the last error returned to us from Redis, if any.
Returns whether the connection is in ATOMIC, MULTI, or PIPELINE mode
Retrieve the value of a configuration setting as set by Redis::setOption()
Get the persistent connection ID, if there is one.
Get the port we are connected to. This number will be zero if we are connected to a unix socket.
Retrieve a substring of a string by index.
Get the longest common subsequence between two string keys.
Get the currently set read timeout on the connection.
Sets a key and returns any previously set value, if the key already existed.
Retrieve any set connection timeout
No description
Remove one or more fields from a hash.
Checks whether a field exists in a hash.
No description
Read every field and value from a hash.
Increment a hash field's value by an integer
Increment a hash field by a floating point value
Retrieve all of the fields of a hash.
Get the number of fields in a hash.
Get one or more fields from a hash.
Add or update one or more hash fields and values
Get one or more random field from a hash.
No description
Set a hash field and value, but only if that field does not exist
Get the string length of a hash field
Get all of the values from a hash.
Iterate over the fields and values of a hash in an incremental fashion.
Increment a key's value, optionally by a specifc amount.
Increment a key by a specific integer value
Increment a numeric key by a floating point value.
Retrieve information about the connected redis-server. If no arguments are passed to this function, redis will return every info field. Alternatively you may pass a specific section you want returned (e.g. 'server', or 'memory') to receive only information pertaining to that section.
Check if we are currently connected to a Redis instance.
Retrieve the lenght of a list.
Move an element from one list into another.
Pop one or more elements off a list.
Retrieve the index of an element in a list.
Prepend one or more elements to a list.
Append one or more elements to a list.
Prepend an element to a list but only if the list exists
Append an element to a list but only if the list exists
Set a list element at an index to a specific value.
Retrieve the last time Redis' database was persisted to disk.
Get the element of a list by its index.
Retrieve elements from a list.
Remove one or more matching elements from a list.
Trim a list to a subrange of elements.
Get one ore more string keys.
No description
Move a key to a different database on the same redis instance.
Set one ore more string keys.
Set one ore more string keys but only if none of the key exist.
Begin a transaction.
No description
No description
No description
Remove the expiration from a key.
Sets an expiration in milliseconds on a given key. If connected to Redis >= 7.0.0 you can pass an optional mode argument that modifies how the command will execute.
Set a key's expiration to a specific Unix Timestamp in milliseconds. If connected to Redis >= 7.0.0 you can pass an optional 'mode' argument.
Add one or more elements to a Redis HyperLogLog key
Retrieve the cardinality of a Redis HyperLogLog key.
Merge one or more source HyperLogLog sets into a destination set.
PING the redis server with an optional string argument.
Enter into pipeline mode.
No description
Set a key with an expiration time in milliseconds
Subscribe to one or more glob-style patterns
Get a keys time to live in milliseconds.
Publish a message to a pubsub channel
No description
Unsubscribe from one or more channels by pattern
Pop one or more elements from the end of a list.
Return a random key from the current database
Execute any arbitrary Redis command by name.
Unconditionally rename a key from $old_name to $new_name
Renames $key_src to $key_dst but only if newkey does not exist.
Reset the state of the connection.
Restore a key by the binary payload generated by the DUMP command.
Query whether the connected instance is a primary or replica
Atomically pop an element off the end of a Redis LIST and push it to the beginning of another.
Add one or more values to a Redis SET key.
Add one ore more values to a Redis SET key. This is an alternative to Redis::sadd() but instead of being variadic, takes a single array of values.
Given one or more Redis SETS, this command returns all of the members from the first set that are not in any subsequent set.
This method performs the same operation as SDIFF except it stores the resulting diff values in a specified destination key.
Given one or more Redis SET keys, this command will return all of the elements that are in every one.
Compute the intersection of one or more sets and return the cardinality of the result.
Perform the intersection of one or more Redis SETs, storing the result in a destination key, rather than returning them.
Retrieve every member from a set key.
Check if one or more values are members of a set.
Pop a member from one set and push it onto another. This command will create the destination set if it does not currently exist.
Remove one or more elements from a set.
Retrieve one or more random members of a set.
Returns the union of one or more Redis SET keys.
Perform a union of one or more Redis SET keys and store the result in a new set
Persist the Redis database to disk. This command will block the server until the save is completed. For a nonblocking alternative, see Redis::bgsave().
Incrementally scan the Redis keyspace, with optional pattern and type matching.
Retrieve the number of members in a Redis set.
An administrative command used to interact with LUA scripts stored on the server.
Select a specific Redis database.
Create or set a Redis STRING key to a value.
Set a specific bit in a Redis string to zero or one
Update or append to a Redis string at a specific starting index
Set a configurable option on the Redis object.
Set a Redis STRING key with a specific expiration in seconds.
Set a key to a value, but only if that key does not already exist.
Check whether a given value is the member of a Redis SET.
Turn a redis instance into a replica of another or promote a replica to a primary.
Used to turn a Redis instance into a replica of another, or to remove replica status promoting the instance to a primary.
Update one or more keys last modified metadata.
Interact with Redis' slowlog functionality in various ways, depending on the value of 'operation'.
Sort the contents of a Redis key in various ways.
This is simply a read-only variant of the sort command
No description
No description
No description
No description
Remove one or more values from a Redis SET key.
Scan the members of a redis SET key.
Retrieve the length of a Redis STRING key.
Subscribe to one or more Redis pubsub channels.
Atomically swap two Redis databases so that all of the keys in the source database will now be in the destination database and vice-versa.
Retrieve the server time from the connected Redis instance.
Get the amount of time a Redis key has before it will expire, in seconds.
Get the type of a given Redis key.
Delete one or more keys from the Redis database. Unlike this operation, the actual deletion is asynchronous, meaning it is safe to delete large keys without fear of Redis blocking for a long period of time.
Unsubscribe from one or more subscribed channels.
Remove any previously WATCH'ed keys in a transaction.
Watch one or more keys for conditional execution of a transaction.
Block the client up to the provided timeout until a certain number of replicas have confirmed recieving them.
Acknowledge one ore more messages that are pending (have been consumed using XREADGROUP but not yet acknowledged by XACK.)
Append a message to a stream.
This command allows a consumer to claim pending messages that have been idle for a specified period of time.
This method allows a consumer to take ownership of pending stream entries, by ID. Another
command that does much the same thing but does not require passing specific IDs is Redis::xAutoClaim
.
Remove one or more specific IDs from a stream.
XGROUP
Retrieve information about a stream key.
Get the number of messages in a Redis STREAM key.
Interact with stream messages that have been consumed by a consumer group but not yet acknowledged with XACK.
Get a range of entries from a STREAM key.
Consume one or more unconsumed elements in one or more streams.
Read one or more messages using a consumer group.
Get a range of entries from a STREAM ke in reverse cronological order.
Truncate a STREAM key in various ways.
Add one or more elements and scores to a Redis sorted set.
Return the number of elements in a sorted set.
Count the number of members in a sorted set with scores inside a provided range.
Create or increment the score of a member in a Redis sorted set
Count the number of elements in a sorted set whos members fall within the provided lexographical range.
Retrieve the score of one or more members in a sorted set.
Pop one or more of the highest scoring elements from a sorted set.
Pop one or more of the lowest scoring elements from a sorted set.
Retrieve a range of elements of a sorted set between a start and end point.
Retrieve a range of elements from a sorted set by legographical range.
Retrieve a range of members from a sorted set by their score.
This command is similar to ZRANGE except that instead of returning the values directly it will store them in a destination key provided by the user
Retrieve one or more random members from a Redis sorted set.
Get the rank of a member of a sorted set, by score.
Remove one or more members from a Redis sorted set.
Remove zero or more elements from a Redis sorted set by legographical range.
Remove one or more members of a sorted set by their rank.
Remove one or more members of a sorted set by their score.
List the members of a Redis sorted set in reverse order
List members of a Redis sorted set within a legographical range, in reverse order.
List elements from a Redis sorted set by score, highest to lowest
Retrieve a member of a sorted set by reverse rank.
Get the score of a member of a sorted set.
Given one or more sorted set key names, return every element that is in the first set but not any of the others.
Store the difference of one or more sorted sets in a destination sorted set.
Compute the intersection of one or more sorted sets and return the members
Similar to ZINTER but instead of returning the intersected values, this command returns the cardinality of the intersected set.
Compute the intersection of one ore more sorted sets storing the result in a new sorted set.
Scan the members of a sorted set incrementally, using a cursor
Retrieve the union of one or more sorted sets
Perform a union on one or more Redis sets and store the result in a destination sorted set.
Details
Redis
__construct(array $options = null)
Create a new Redis instance. If passed sufficient information in the options array it is also possible to connect to an instance at the same time.
NOTE: Below is an example options array with various setting
$options = [
'host' => 'localhost',
'port' => 6379,
'readTimeout' => 2.5,
'connectTimeout' => 2.5,
'persistent' => true,
// Valid formats: NULL, ['user', 'pass'], 'pass', or ['pass']
'auth' => ['phpredis', 'phpredis'],
// See PHP stream options for valid SSL configuration settings.
'ssl' => ['verify_peer' => false],
// How quickly to retry a connection after we time out or it closes.
// Note that this setting is overridden by 'backoff' strategies.
'retryInterval' => 100,
// Which backoff algorithm to use. 'decorrelated jitter' is
// likely the best one for most solution, but there are many
// to choose from:
// REDIS_BACKOFF_ALGORITHM_DEFAULT
// REDIS_BACKOFF_ALGORITHM_CONSTANT
// REDIS_BACKOFF_ALGORITHM_UNIFORM
// REDIS_BACKOFF_ALGORITHM_EXPONENTIAL
// REDIS_BACKOFF_ALGORITHM_FULL_JITTER
// REDIS_BACKOFF_ALGORITHM_EQUAL_JITTER
// REDIS_BACKOFF_ALGORITHM_DECORRELATED_JITTER
// 'base', and 'cap' are in milliseconds and represent the first
// delay redis will use when reconnecting, and the maximum delay
// we will reach while retrying.
'backoff' => [
'algorithm' => Redis::BACKOFF_ALGORITHM_DECORRELATED_JITTER,
'base' => 500,
'cap' => 750,
]
];
Note: If you do wish to connect via the constructor, only 'host' is strictly required, which will cause PhpRedis to connect to that host on Redis' default port (6379).
__destruct()
No description
string
_compress(string $value)
Compress a value with the currently configured compressor as set with Redis::setOption().
string
_uncompress(string $value)
Uncompress the provided argument that has been compressed with the currently configured compressor as set with Redis::setOption().
string
_prefix(string $key)
Prefix the passed argument with the currently set key prefix as set with Redis::setOption().
string
_serialize(mixed $value)
Serialize the provided value with the currently set serializer as set with Redis::setOption().
mixed
_unserialize(string $value)
Unserialize the passed argument with the currently set serializer as set with Redis::setOption().
string
_pack(mixed $value)
Pack the provided value with the configured serializer and compressor as set with Redis::setOption().
mixed
_unpack(string $value)
Unpack the provided value with the configured compressor and serializer as set with Redis::setOption().
mixed
acl(string $subcmd, string ...$args)
No description
Redis|int|false
append(string $key, mixed $value)
Append data to a Redis STRING key.
Redis|bool
auth(mixed $credentials)
Authenticate a Redis connection after its been established.
$redis->auth('password'); $redis->auth(['password']); $redis->auth(['username', 'password']);
Redis|bool
bgSave()
Execute a save of the Redis database in the background.
Redis|bool
bgrewriteaof()
Asynchronously rewrite Redis' append-only file
Redis|int|false
bitcount(string $key, int $start = 0, int $end = -1, bool $bybit = false)
Count the number of set bits in a Redis string.
Redis|int|false
bitop(string $operation, string $deskey, string $srckey, string ...$other_keys)
No description
Redis|int|false
bitpos(string $key, bool $bit, int $start = 0, int $end = -1, bool $bybit = false)
Return the position of the first bit set to 0 or 1 in a string.
Redis|array|null|false
blPop(string|array $key_or_keys, string|float|int $timeout_or_key, mixed ...$extra_args)
Pop an element off the beginning of a Redis list or lists, potentially blocking up to a specified timeout. This method may be called in two distinct ways, of which examples are provided below.
Redis|array|null|false
brPop(string|array $key_or_keys, string|float|int $timeout_or_key, mixed ...$extra_args)
Pop an element off of the end of a Redis list or lists, potentially blocking up to a specified timeout.
The calling convention is identical to Redis::blPop() so see that documentation for more details.
Redis|string|false
brpoplpush(string $src, string $dst, int|float $timeout)
Pop an element from the end of a Redis list, pushing it to the beginning of another Redis list, optionally blocking up to a specified timeout.
Redis|array|false
bzPopMax(string|array $key, string|int $timeout_or_key, mixed ...$extra_args)
POP the maximum scoring element off of one or more sorted sets, blocking up to a specified timeout if no elements are available.
Following are examples of the two main ways to call this method.
NOTE: We reccomend calling this function with an array and a timeout as the other strategy may be deprecated in future versions of PhpRedis
Redis|array|false
bzPopMin(string|array $key, string|int $timeout_or_key, mixed ...$extra_args)
POP the minimum scoring element off of one or more sorted sets, blocking up to a specified timeout if no elements are available
This command is identical in semantics to bzPopMax so please see that method for more information.
Redis|array|null|false
bzmpop(float $timeout, array $keys, string $from, int $count = 1)
POP one or more elements from one or more sorted sets, blocking up to a specified amount of time when no elements are available.
Redis|array|null|false
zmpop(array $keys, string $from, int $count = 1)
POP one or more of the highest or lowest scoring elements from one or more sorted sets.
Redis|array|null|false
blmpop(float $timeout, array $keys, string $from, int $count = 1)
Pop one or more elements from one or more Redis LISTs, blocking up to a specified timeout when no elements are available.
Redis|array|null|false
lmpop(array $keys, string $from, int $count = 1)
Pop one or more elements off of one or more Redis LISTs.
bool
clearLastError()
Reset any last error on the connection to NULL
mixed
client(string $opt, mixed ...$args)
No description
bool
close()
No description
mixed
command(string $opt = null, string|array $arg)
No description
mixed
config(string $operation, array|string|null $key_or_settings = NULL, string|null $value = NULL)
Execute the Redis CONFIG command in a variety of ways.
What the command does in particular depends on the $operation
qualifier.
Operations that PhpRedis supports are: RESETSTAT, REWRITE, GET, and SET.
bool
connect(string $host, int $port = 6379, float $timeout = 0, string $persistent_id = null, int $retry_interval = 0, float $read_timeout = 0, array $context = null)
No description
Redis|bool
copy(string $src, string $dst, array $options = null)
Make a copy of a key.
$redis = new Redis(['host' => 'localhost']);
Redis|int|false
dbSize()
Return the number of keys in the currently selected Redis database.
Redis|string
debug(string $key)
No description
Redis|int|false
decr(string $key, int $by = 1)
Decrement a Redis integer by 1 or a provided value.
Redis|int|false
decrBy(string $key, int $value)
Decrement a redis integer by a value
Redis|int|false
del(array|string $key, string ...$other_keys)
Delete one or more keys from Redis.
This method can be called in two distinct ways. The first is to pass a single array of keys to delete, and the second is to pass N arguments, all names of keys. See below for an example of both strategies.
Redis|int|false
delete(array|string $key, string ...$other_keys)
deprecated
deprecated
No description
Redis|bool
discard()
Discard a transaction currently in progress.
Redis|string
dump(string $key)
Dump Redis' internal binary representation of a key.
$redis->zRange('new-zset', 0, -1, true);
Redis|string|false
echo(string $str)
Have Redis repeat back an arbitrary string to the client.
mixed
eval(string $script, array $args = [], int $num_keys = 0)
Execute a LUA script on the redis server.
mixed
eval_ro(string $script_sha, array $args = [], int $num_keys = 0)
This is simply the read-only variant of eval, meaning the underlying script may not modify data in redis.
mixed
evalsha(string $sha1, array $args = [], int $num_keys = 0)
Execute a LUA script on the server but instead of sending the script, send the SHA1 hash of the script.
mixed
evalsha_ro(string $sha1, array $args = [], int $num_keys = 0)
This is simply the read-only variant of evalsha, meaning the underlying script may not modify data in redis.
Redis|array|false
exec()
Execute either a MULTI or PIPELINE block and return the array of replies.
Redis|int|bool
exists(mixed $key, mixed ...$other_keys)
Test if one or more keys exist.
Redis|bool
expire(string $key, int $timeout, string|null $mode = NULL)
Sets an expiration in seconds on the key in question. If connected to redis-server >= 7.0.0 you may send an additional "mode" argument which modifies how the command will execute.
Redis|bool
expireAt(string $key, int $timestamp, string|null $mode = NULL)
Set a key to expire at an exact unix timestamp.
Redis|bool
failover(array|null $to = null, bool $abort = false, int $timeout = 0)
No description
Redis|int|false
expiretime(string $key)
Get the expiration of a given key as a unix timestamp
Redis|int|false
pexpiretime(string $key)
Get the expriation timestamp of a given Redis key but in milliseconds.
Redis|bool
flushAll(bool|null $sync = null)
Deletes every key in all Redis databases
Redis|bool
flushDB(bool|null $sync = null)
Deletes all the keys of the currently selected database.
Redis|int|false
geoadd(string $key, float $lng, float $lat, string $member, mixed ...$other_triples_and_options)
Add one or more members to a geospacial sorted set
Redis|float|false
geodist(string $key, string $src, string $dst, string|null $unit = null)
Get the distance between two members of a geospacially encoded sorted set.
Redis|array|false
geohash(string $key, string $member, string ...$other_members)
Retrieve one or more GeoHash encoded strings for members of the set.
Redis|array|false
geopos(string $key, string $member, string ...$other_members)
Return the longitude and lattitude for one or more members of a geospacially encoded sorted set.
mixed
georadius(string $key, float $lng, float $lat, float $radius, string $unit, array $options = [])
Retrieve members of a geospacially sorted set that are within a certain radius of a location.
mixed
georadius_ro(string $key, float $lng, float $lat, float $radius, string $unit, array $options = [])
A readonly variant of GEORADIUS
that may be executed on replicas.
mixed
georadiusbymember(string $key, string $member, float $radius, string $unit, array $options = [])
Similar to GEORADIUS
except it uses a member as the center of the query.
mixed
georadiusbymember_ro(string $key, string $member, float $radius, string $unit, array $options = [])
This is the read-only variant of GEORADIUSBYMEMBER
that can be run on replicas.
array
geosearch(string $key, array|string $position, array|int|float $shape, string $unit, array $options = [])
Search a geospacial sorted set for members in various ways.
Redis|array|int|false
geosearchstore(string $dst, string $src, array|string $position, array|int|float $shape, string $unit, array $options = [])
Search a geospacial sorted set for members within a given area or range, storing the results into a new set.
mixed
get(string $key)
Retrieve a string keys value.
mixed
getAuth()
Get the authentication information on the connection, if any.
Redis|int|false
getBit(string $key, int $idx)
Get the bit at a given index in a string key.
Redis|string|bool
getEx(string $key, array $options = [])
Get the value of a key and optionally set it's expiration.
int
getDBNum()
Get the database number PhpRedis thinks we're connected to.
This value is updated internally in PhpRedis each time Redis::select is called.
Redis|string|bool
getDel(string $key)
Get a key from Redis and delete it in an atomic operation.
string
getHost()
Return the host or Unix socket we are connected to.
string|null
getLastError()
Get the last error returned to us from Redis, if any.
int
getMode()
Returns whether the connection is in ATOMIC, MULTI, or PIPELINE mode
mixed
getOption(int $option)
Retrieve the value of a configuration setting as set by Redis::setOption()
string|null
getPersistentID()
Get the persistent connection ID, if there is one.
int
getPort()
Get the port we are connected to. This number will be zero if we are connected to a unix socket.
Redis|string|false
getRange(string $key, int $start, int $end)
Retrieve a substring of a string by index.
Redis|string|array|int|false
lcs(string $key1, string $key2, array|null $options = NULL)
Get the longest common subsequence between two string keys.
float
getReadTimeout()
Get the currently set read timeout on the connection.
Redis|string|false
getset(string $key, mixed $value)
Sets a key and returns any previously set value, if the key already existed.
float|false
getTimeout()
Retrieve any set connection timeout
int|false
getTransferredBytes()
No description
Redis|int|false
hDel(string $key, string $field, string ...$other_fields)
Remove one or more fields from a hash.
Redis|bool
hExists(string $key, string $field)
Checks whether a field exists in a hash.
mixed
hGet(string $key, string $member)
No description
Redis|array|false
hGetAll(string $key)
Read every field and value from a hash.
Redis|int|false
hIncrBy(string $key, string $field, int $value)
Increment a hash field's value by an integer
Redis|float|false
hIncrByFloat(string $key, string $field, float $value)
Increment a hash field by a floating point value
Redis|array|false
hKeys(string $key)
Retrieve all of the fields of a hash.
Redis|int|false
hLen(string $key)
Get the number of fields in a hash.
Redis|array|false
hMget(string $key, array $fields)
Get one or more fields from a hash.
Redis|bool
hMset(string $key, array $fieldvals)
Add or update one or more hash fields and values
Redis|string|array
hRandField(string $key, array $options = null)
Get one or more random field from a hash.
Redis|int|false
hSet(string $key, string $member, mixed $value)
No description
Redis|bool
hSetNx(string $key, string $field, string $value)
Set a hash field and value, but only if that field does not exist
Redis|int|false
hStrLen(string $key, string $field)
Get the string length of a hash field
Redis|array|false
hVals(string $key)
Get all of the values from a hash.
Redis|array|bool
hscan(string $key, int|null $iterator, string|null $pattern = null, int $count = 0)
Iterate over the fields and values of a hash in an incremental fashion.
Redis|int|false
incr(string $key, int $by = 1)
Increment a key's value, optionally by a specifc amount.
Redis|int|false
incrBy(string $key, int $value)
Increment a key by a specific integer value
Redis|float|false
incrByFloat(string $key, float $value)
Increment a numeric key by a floating point value.
Redis|array|false
info(string ...$sections)
Retrieve information about the connected redis-server. If no arguments are passed to this function, redis will return every info field. Alternatively you may pass a specific section you want returned (e.g. 'server', or 'memory') to receive only information pertaining to that section.
If connected to Redis server >= 7.0.0 you may pass multiple optional sections.
bool
isConnected()
Check if we are currently connected to a Redis instance.
Redis|array|false
keys(string $pattern)
No description
Redis|int|false
lInsert(string $key, string $pos, mixed $pivot, mixed $value)
No description
Redis|int|false
lLen(string $key)
Retrieve the lenght of a list.
Redis|string|false
lMove(string $src, string $dst, string $wherefrom, string $whereto)
Move an element from one list into another.
Redis|bool|string|array
lPop(string $key, int $count = 0)
Pop one or more elements off a list.
Redis|null|bool|int|array
lPos(string $key, mixed $value, array $options = null)
Retrieve the index of an element in a list.
Redis|int|false
lPush(string $key, mixed ...$elements)
Prepend one or more elements to a list.
Redis|int|false
rPush(string $key, mixed ...$elements)
Append one or more elements to a list.
Redis|int|false
lPushx(string $key, mixed $value)
Prepend an element to a list but only if the list exists
Redis|int|false
rPushx(string $key, mixed $value)
Append an element to a list but only if the list exists
Redis|bool
lSet(string $key, int $index, mixed $value)
Set a list element at an index to a specific value.
int
lastSave()
Retrieve the last time Redis' database was persisted to disk.
mixed
lindex(string $key, int $index)
Get the element of a list by its index.
Redis|array|false
lrange(string $key, int $start, int $end)
Retrieve elements from a list.
Redis|int|false
lrem(string $key, mixed $value, int $count = 0)
Remove one or more matching elements from a list.
Redis|bool
ltrim(string $key, int $start, int $end)
Trim a list to a subrange of elements.
Redis|array
mget(array $keys)
Get one ore more string keys.
Redis|bool
migrate(string $host, int $port, string|array $key, int $dstdb, int $timeout, bool $copy = false, bool $replace = false, mixed $credentials = NULL)
No description
Redis|bool
move(string $key, int $index)
Move a key to a different database on the same redis instance.
Redis|bool
mset(array $key_values)
Set one ore more string keys.
Redis|bool
msetnx(array $key_values)
Set one ore more string keys but only if none of the key exist.
bool|Redis
multi(int $value = Redis::MULTI)
Begin a transaction.
Redis|int|string|false
object(string $subcommand, string $key)
No description
bool
open(string $host, int $port = 6379, float $timeout = 0, string $persistent_id = NULL, int $retry_interval = 0, float $read_timeout = 0, array $context = NULL)
deprecated
deprecated
No description
bool
pconnect(string $host, int $port = 6379, float $timeout = 0, string $persistent_id = NULL, int $retry_interval = 0, float $read_timeout = 0, array $context = NULL)
No description
Redis|bool
persist(string $key)
Remove the expiration from a key.
bool
pexpire(string $key, int $timeout, string|null $mode = NULL)
Sets an expiration in milliseconds on a given key. If connected to Redis >= 7.0.0 you can pass an optional mode argument that modifies how the command will execute.
Redis::expire() for a description of the mode argument.
Redis|bool
pexpireAt(string $key, int $timestamp, string|null $mode = NULL)
Set a key's expiration to a specific Unix Timestamp in milliseconds. If connected to Redis >= 7.0.0 you can pass an optional 'mode' argument.
Redis|int
pfadd(string $key, array $elements)
Add one or more elements to a Redis HyperLogLog key
Redis|int
pfcount(string $key)
Retrieve the cardinality of a Redis HyperLogLog key.
Redis|bool
pfmerge(string $dst, array $srckeys)
Merge one or more source HyperLogLog sets into a destination set.
Redis|string|bool
ping(string $message = NULL)
PING the redis server with an optional string argument.
bool|Redis
pipeline()
Enter into pipeline mode.
Pipeline mode is the highest performance way to send many commands to Redis as they are aggregated into one stream of commands and then all sent at once when the user calls Redis::exec().
NOTE: That this is shorthand for Redis::multi(Redis::PIPELINE)
bool
popen(string $host, int $port = 6379, float $timeout = 0, string $persistent_id = NULL, int $retry_interval = 0, float $read_timeout = 0, array $context = NULL)
deprecated
deprecated
No description
Redis|bool
psetex(string $key, int $expire, mixed $value)
Set a key with an expiration time in milliseconds
bool
psubscribe(array $patterns, callable $cb)
Subscribe to one or more glob-style patterns
Redis|int|false
pttl(string $key)
Get a keys time to live in milliseconds.
Redis|int|false
publish(string $channel, string $message)
Publish a message to a pubsub channel
mixed
pubsub(string $command, mixed $arg = null)
No description
Redis|array|bool
punsubscribe(array $patterns)
Unsubscribe from one or more channels by pattern
Redis|array|string|bool
rPop(string $key, int $count = 0)
Pop one or more elements from the end of a list.
Redis|string|false
randomKey()
Return a random key from the current database
mixed
rawcommand(string $command, mixed ...$args)
Execute any arbitrary Redis command by name.
Redis|bool
rename(string $old_name, string $new_name)
Unconditionally rename a key from $old_name to $new_name
Redis|bool
renameNx(string $key_src, string $key_dst)
Renames $key_src to $key_dst but only if newkey does not exist.
Redis|bool
reset()
Reset the state of the connection.
Redis|bool
restore(string $key, int $ttl, string $value, array|null $options = NULL)
Restore a key by the binary payload generated by the DUMP command.
mixed
role()
Query whether the connected instance is a primary or replica
Redis|string|false
rpoplpush(string $srckey, string $dstkey)
Atomically pop an element off the end of a Redis LIST and push it to the beginning of another.
Redis|int|false
sAdd(string $key, mixed $value, mixed ...$other_values)
Add one or more values to a Redis SET key.
int
sAddArray(string $key, array $values)
Add one ore more values to a Redis SET key. This is an alternative to Redis::sadd() but instead of being variadic, takes a single array of values.
Redis|array|false
sDiff(string $key, string ...$other_keys)
Given one or more Redis SETS, this command returns all of the members from the first set that are not in any subsequent set.
Redis|int|false
sDiffStore(string $dst, string $key, string ...$other_keys)
This method performs the same operation as SDIFF except it stores the resulting diff values in a specified destination key.
Redis|array|false
sInter(array|string $key, string ...$other_keys)
Given one or more Redis SET keys, this command will return all of the elements that are in every one.
Redis|int|false
sintercard(array $keys, int $limit = -1)
Compute the intersection of one or more sets and return the cardinality of the result.
Redis|int|false
sInterStore(array|string $key, string ...$other_keys)
Perform the intersection of one or more Redis SETs, storing the result in a destination key, rather than returning them.
Redis|array|false
sMembers(string $key)
Retrieve every member from a set key.
Redis|array|false
sMisMember(string $key, string $member, string ...$other_members)
Check if one or more values are members of a set.
Redis|bool
sMove(string $src, string $dst, mixed $value)
Pop a member from one set and push it onto another. This command will create the destination set if it does not currently exist.
Redis|string|array|false
sPop(string $key, int $count = 0)
Remove one or more elements from a set.
Redis|string|array|false
sRandMember(string $key, int $count = 0)
Retrieve one or more random members of a set.
Redis|array|false
sUnion(string $key, string ...$other_keys)
Returns the union of one or more Redis SET keys.
Redis|int|false
sUnionStore(string $dst, string $key, string ...$other_keys)
Perform a union of one or more Redis SET keys and store the result in a new set
Redis|bool
save()
Persist the Redis database to disk. This command will block the server until the save is completed. For a nonblocking alternative, see Redis::bgsave().
array|false
scan(int|null $iterator, string|null $pattern = null, int $count = 0, string $type = NULL)
Incrementally scan the Redis keyspace, with optional pattern and type matching.
A note about Redis::SCAN_NORETRY and Redis::SCAN_RETRY.
For convenience, PhpRedis can retry SCAN commands itself when Redis returns an empty array of keys with a nonzero iterator. This can happen when matching against a pattern that very few keys match inside a key space with a great many keys. The following example demonstrates how to use Redis::scan() with the option disabled and enabled.
Redis|int|false
scard(string $key)
Retrieve the number of members in a Redis set.
mixed
script(string $command, mixed ...$args)
An administrative command used to interact with LUA scripts stored on the server.
Redis|bool
select(int $db)
Select a specific Redis database.
Redis|string|bool
set(string $key, mixed $value, mixed $options = NULL)
Create or set a Redis STRING key to a value.
Redis|int|false
setBit(string $key, int $idx, bool $value)
Set a specific bit in a Redis string to zero or one
Redis|int|false
setRange(string $key, int $index, string $value)
Update or append to a Redis string at a specific starting index
bool
setOption(int $option, mixed $value)
Set a configurable option on the Redis object.
Following are a list of options you can set:
| OPTION | TYPE | DESCRIPTION |
|---|---|---|
| OPT_MAX_RETRIES | int | The maximum number of times Redis will attempt to reconnect if it gets disconnected, before throwing an exception. |
| OPT_SCAN | enum | Redis::OPT_SCAN_RETRY, or Redis::OPT_SCAN_NORETRY. Whether PhpRedis should automatically SCAN again when zero keys but a nonzero iterator are returned. |
| OPT_SERIALIZER | enum | Set the automatic data serializer.Redis::SERIALIZER_NONE Redis::SERIALIZER_PHP Redis::SERIALIZER_IGBINARY Redis::SERIALIZER_MSGPACK , Redis::SERIALIZER_JSON |
| OPT_PREFIX | string | A string PhpRedis will use to prefix every key we read or write. |
| OPT_READ_TIMEOUT | float | How long PhpRedis will block for a response from Redis before throwing a 'read error on connection' exception. |
| OPT_TCP_KEEPALIVE | bool | Set or disable TCP_KEEPALIVE on the connection. |
| OPT_COMPRESSION | enum | Set the compression algorithmRedis::COMPRESSION_NONE Redis::COMPRESSION_LZF Redis::COMPRESSION_LZ4 Redis::COMPRESSION_ZSTD |
| OPT_REPLY_LITERAL | bool | If set to true, PhpRedis will return the literal string Redis returns for LINE replies (e.g. '+OK'), rather than true . |
| OPT_COMPRESSION_LEVEL | int | Set a specific compression level if Redis is compressing data. |
| OPT_NULL_MULTIBULK_AS_NULL | bool | Causes PhpRedis to return NULL rather than false for NULL MULTIBULK replies |
| OPT_BACKOFF_ALGORITHM | enum | The exponential backoff strategy to use. |
| OPT_BACKOFF_BASE | int | The minimum delay between retries when backing off. |
| OPT_BACKOFF_CAP | int | The maximum delay between replies when backing off. |
Redis|bool
setex(string $key, int $expire, mixed $value)
Set a Redis STRING key with a specific expiration in seconds.
Redis|bool
setnx(string $key, mixed $value)
Set a key to a value, but only if that key does not already exist.
Redis|bool
sismember(string $key, mixed $value)
Check whether a given value is the member of a Redis SET.
Redis|bool
slaveof(string $host = NULL, int $port = 6379)
deprecated
deprecated
Turn a redis instance into a replica of another or promote a replica to a primary.
This method and the corresponding command in Redis has been marked deprecated and users should instead use Redis::replicaof() if connecting to redis-server
= 5.0.0.
Redis|bool
replicaof(string $host = NULL, int $port = 6379)
Used to turn a Redis instance into a replica of another, or to remove replica status promoting the instance to a primary.
Redis|int|false
touch(array|string $key_or_array, string ...$more_keys)
Update one or more keys last modified metadata.
mixed
slowlog(string $operation, int $length = 0)
Interact with Redis' slowlog functionality in various ways, depending on the value of 'operation'.
mixed
sort(string $key, array|null $options = null)
Sort the contents of a Redis key in various ways.
mixed
sort_ro(string $key, array|null $options = null)
This is simply a read-only variant of the sort command
array
sortAsc(string $key, string|null $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, string|null $store = null)
deprecated
deprecated
No description
array
sortAscAlpha(string $key, string|null $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, string|null $store = null)
deprecated
deprecated
No description
array
sortDesc(string $key, string|null $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, string|null $store = null)
deprecated
deprecated
No description
array
sortDescAlpha(string $key, string|null $pattern = null, mixed $get = null, int $offset = -1, int $count = -1, string|null $store = null)
deprecated
deprecated
No description
Redis|int|false
srem(string $key, mixed $value, mixed ...$other_values)
Remove one or more values from a Redis SET key.
array|false
sscan(string $key, int|null $iterator, string|null $pattern = null, int $count = 0)
Scan the members of a redis SET key.
Redis|int|false
strlen(string $key)
Retrieve the length of a Redis STRING key.
bool
subscribe(array $channels, callable $cb)
Subscribe to one or more Redis pubsub channels.
Redis|bool
swapdb(int $src, int $dst)
Atomically swap two Redis databases so that all of the keys in the source database will now be in the destination database and vice-versa.
Note: This command simply swaps Redis' internal pointer to the database and is therefore very fast, regardless of the size of the underlying databases.
Redis|array
time()
Retrieve the server time from the connected Redis instance.
Redis|int|false
ttl(string $key)
Get the amount of time a Redis key has before it will expire, in seconds.
Redis|int|false
type(string $key)
Get the type of a given Redis key.
Redis|int|false
unlink(array|string $key, string ...$other_keys)
Delete one or more keys from the Redis database. Unlike this operation, the actual deletion is asynchronous, meaning it is safe to delete large keys without fear of Redis blocking for a long period of time.
Redis|array|bool
unsubscribe(array $channels)
Unsubscribe from one or more subscribed channels.
Redis|bool
unwatch()
Remove any previously WATCH'ed keys in a transaction.
Redis|bool
watch(array|string $key, string ...$other_keys)
Watch one or more keys for conditional execution of a transaction.
int|false
wait(int $numreplicas, int $timeout)
Block the client up to the provided timeout until a certain number of replicas have confirmed recieving them.
int|false
xack(string $key, string $group, array $ids)
Acknowledge one ore more messages that are pending (have been consumed using XREADGROUP but not yet acknowledged by XACK.)
Redis|string|false
xadd(string $key, string $id, array $values, int $maxlen = 0, bool $approx = false, bool $nomkstream = false)
Append a message to a stream.
Redis|bool|array
xautoclaim(string $key, string $group, string $consumer, int $min_idle, string $start, int $count = -1, bool $justid = false)
This command allows a consumer to claim pending messages that have been idle for a specified period of time.
Its purpose is to provide a mechanism for picking up messages that may have had a failed consumer.
Redis|array|bool
xclaim(string $key, string $group, string $consumer, int $min_idle, array $ids, array $options)
This method allows a consumer to take ownership of pending stream entries, by ID. Another
command that does much the same thing but does not require passing specific IDs is Redis::xAutoClaim
.
Redis|int|false
xdel(string $key, array $ids)
Remove one or more specific IDs from a stream.
mixed
xgroup(string $operation, string $key = null, string $group = null, string $id_or_consumer = null, bool $mkstream = false, int $entries_read = -2)
XGROUP
Perform various operation on consumer groups for a particular Redis STREAM. What the command does is primarily based on which operation is passed.
mixed
xinfo(string $operation, string|null $arg1 = null, string|null $arg2 = null, int $count = -1)
Retrieve information about a stream key.
Redis|int|false
xlen(string $key)
Get the number of messages in a Redis STREAM key.
Redis|array|false
xpending(string $key, string $group, string|null $start = null, string|null $end = null, int $count = -1, string|null $consumer = null)
Interact with stream messages that have been consumed by a consumer group but not yet acknowledged with XACK.
Redis|array|bool
xrange(string $key, string $start, string $end, int $count = -1)
Get a range of entries from a STREAM key.
Redis|array|bool
xread(array $streams, int $count = -1, int $block = -1)
Consume one or more unconsumed elements in one or more streams.
Redis|array|bool
xreadgroup(string $group, string $consumer, array $streams, int $count = 1, int $block = 1)
Read one or more messages using a consumer group.
Redis|array|bool
xrevrange(string $key, string $end, string $start, int $count = -1)
Get a range of entries from a STREAM ke in reverse cronological order.
Redis|int|false
xtrim(string $key, string $threshold, bool $approx = false, bool $minid = false, int $limit = -1)
Truncate a STREAM key in various ways.
Redis|int|false
zAdd(string $key, array|float $score_or_options, mixed ...$more_scores_and_mems)
Add one or more elements and scores to a Redis sorted set.
Redis|int|false
zCard(string $key)
Return the number of elements in a sorted set.
Redis|int|false
zCount(string $key, string $start, string $end)
Count the number of members in a sorted set with scores inside a provided range.
Redis|float|false
zIncrBy(string $key, float $value, mixed $member)
Create or increment the score of a member in a Redis sorted set
Redis|int|false
zLexCount(string $key, string $min, string $max)
Count the number of elements in a sorted set whos members fall within the provided lexographical range.
Redis|array|false
zMscore(string $key, mixed $member, mixed ...$other_members)
Retrieve the score of one or more members in a sorted set.
Redis|array|false
zPopMax(string $key, int $count = null)
Pop one or more of the highest scoring elements from a sorted set.
Redis|array|false
zPopMin(string $key, int $count = null)
Pop one or more of the lowest scoring elements from a sorted set.
Redis|array|false
zRange(string $key, mixed $start, mixed $end, array|bool|null $options = null)
Retrieve a range of elements of a sorted set between a start and end point.
How the command works in particular is greatly affected by the options that are passed in.
Redis|array|false
zRangeByLex(string $key, string $min, string $max, int $offset = -1, int $count = -1)
Retrieve a range of elements from a sorted set by legographical range.
Redis|array|false
zRangeByScore(string $key, string $start, string $end, array $options = [])
Retrieve a range of members from a sorted set by their score.
Redis|int|false
zrangestore(string $dstkey, string $srckey, string $start, string $end, array|bool|null $options = NULL)
This command is similar to ZRANGE except that instead of returning the values directly it will store them in a destination key provided by the user
Redis|string|array
zRandMember(string $key, array $options = null)
Retrieve one or more random members from a Redis sorted set.
Redis|int|false
zRank(string $key, mixed $member)
Get the rank of a member of a sorted set, by score.
Redis|int|false
zRem(mixed $key, mixed $member, mixed ...$other_members)
Remove one or more members from a Redis sorted set.
Redis|int|false
zRemRangeByLex(string $key, string $min, string $max)
Remove zero or more elements from a Redis sorted set by legographical range.
Redis|int|false
zRemRangeByRank(string $key, int $start, int $end)
Remove one or more members of a sorted set by their rank.
Redis|int|false
zRemRangeByScore(string $key, string $start, string $end)
Remove one or more members of a sorted set by their score.
Redis|array|false
zRevRange(string $key, int $start, int $end, mixed $scores = null)
List the members of a Redis sorted set in reverse order
Redis|array|false
zRevRangeByLex(string $key, string $max, string $min, int $offset = -1, int $count = -1)
List members of a Redis sorted set within a legographical range, in reverse order.
Redis|array|false
zRevRangeByScore(string $key, string $max, string $min, array|bool $options = [])
List elements from a Redis sorted set by score, highest to lowest
Redis|int|false
zRevRank(string $key, mixed $member)
Retrieve a member of a sorted set by reverse rank.
Redis|float|false
zScore(string $key, mixed $member)
Get the score of a member of a sorted set.
Redis|array|false
zdiff(array $keys, array $options = null)
Given one or more sorted set key names, return every element that is in the first set but not any of the others.
Redis|int|false
zdiffstore(string $dst, array $keys)
Store the difference of one or more sorted sets in a destination sorted set.
See Redis::zdiff for a more detailed description of how the diff operation works.
Redis|array|false
zinter(array $keys, array|null $weights = null, array|null $options = null)
Compute the intersection of one or more sorted sets and return the members
Redis|int|false
zintercard(array $keys, int $limit = -1)
Similar to ZINTER but instead of returning the intersected values, this command returns the cardinality of the intersected set.
Redis|int|false
zinterstore(string $dst, array $keys, array|null $weights = null, string|null $aggregate = null)
Compute the intersection of one ore more sorted sets storing the result in a new sorted set.
Redis|array|false
zscan(string $key, int|null $iterator, string|null $pattern = null, int $count = 0)
Scan the members of a sorted set incrementally, using a cursor
Redis|array|false
zunion(array $keys, array|null $weights = null, array|null $options = null)
Retrieve the union of one or more sorted sets
Redis|int|false
zunionstore(string $dst, array $keys, array|null $weights = NULL, string|null $aggregate = NULL)
Perform a union on one or more Redis sets and store the result in a destination sorted set.


A Face in the Crowd
Grade: 75
Before Andy Griffith hit the goldmine with a long-running weekly television series, he made two very good films in the late 1950s, "A Face in the Crowd" and "No Time for Sergeants". The two films presented very different Griffiths. While he begins as a down-home Southerner in both, in "A Face in the Crowd" he becomes a power-mad manipulator, while in "No Time for Sergeants" he never strays from his Gomer Pyle imitation. Guess which film had greater commercial success...
Griffith, in his film debut, plays "Lonesome" Rhodes, a talented entertainer discovered by Patricia Neal in a podunk Arkansas jail. Rhodes gets a local radio show where his mesmerizing home-spun philosophizing and charm makes him a celebrity. Soon he graduates to a Memphis television show, then a national show in New York.
Lee Remick makes her screen debut as Rhodes' young wife, while Walter Matthau is his world-weary writer. Anthony Franciosa is Rhodes' cynical, on-the-move agent.
"A Face in the Crowd" received no Academy Award nominations and stiffed at the box office, despite its quality and the presence of Elia Kazan as director and Budd Schulberg as writer (they had collaborated on "On the Waterfront"). Perhaps the public wasn't ready for the film's indictment of television and its ability to manipulate the masses with phony images.
The weakest part of "A Face in the Crowd" may be the ending, in which good (naturally) triumphs over evil. Milquetoast Matthau delivers a speech to Griffith like a judge passing a sentence, while Griffith goes half-mad upon his come-uppance.
But still, "A Face in the Crowd", if anything, is more relevant today than during its own era. Both Reagan and Clinton have demonstrated that national electoral appeal comes from images more than substance.
<EMAIL_ADDRESS>http://members.tripod.com/~Brian_Koller/movies.html
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


scriptests: Transcript-Based Unit Tests that are Easy to Create and Maintain
Support for using .Rt (transcript) tests
in the tests directory of a package. Provides more
convenience and features than the standard .R/.Rout.save
tests. Tests can be run under R CMD check and also
interactively. Provides source.pkg() for quickly loading
code, DLLs, and data from a package for use in an
edit/compile/test development cycle.
| Version: |
1.0-16 |
| Imports: |
methods |
| Published: |
2016-07-22 |
| Author: |
Tony Plate |
| Maintainer: |
Tony Plate <tplate at acm.org> |
| License: |
GPL-2 | GPL-3 [expanded from: GPL] |
| NeedsCompilation: |
no |
| Materials: |
NEWS |
| CRAN checks: |
scriptests results |
Downloads:
Reverse dependencies:
Linking:
Please use the canonical form
https://CRAN.R-project.org/package=scriptests
to link to this page.


Give A Dinner Party Sitemap
Give A Dinner Party
Homepage
Account
Account2
Account4
All Notification
Dinner Party Booked Tickets
Dinner Party Page Host
Host Step
Invite Friends
Message Inbox
message Inbox Chat
My Events
Pending Request
Profile Edit
Profile Page
profile Photo
Public Profile


runtime.schedt.sudoglock (field)
8 uses
runtime (current package)
mgc.go#L2274: lock(&sched.sudoglock)
mgc.go#L2281: unlock(&sched.sudoglock)
proc.go#L364: lock(&sched.sudoglock)
proc.go#L372: unlock(&sched.sudoglock)
proc.go#L430: lock(&sched.sudoglock)
proc.go#L433: unlock(&sched.sudoglock)
proc.go#L604: lockInit(&sched.sudoglock, lockRankSudog)
runtime2.go#L769: sudoglock mutex
The pages are generated with Golds v0.2.7-preview. (GOOS=darwin GOARCH=amd64)


@(shelter : ShelterDetail, dogs : List[Dog]) @html5.render
Address:
Phone number:
Email address:
Website:
No dogs available at this time!


The task:
"From the websites you visited in the practice assignment, create a list of design and structural features you liked that you may want to use in your designs next week. Think of this as a wishlist. Use appropriate HTML structure (e.g. sections / headers / lists / divs / paragraphs) and answer the following"
Well, looking through a number of websites left me very confused at first. There were so many different styles, features, and a great deal of visual content which seemed to require a high level of artistic talent to acheive. The more I looked, the more despondent I became! However after a bit of time for reflection I realized that the most important thing for me was to simplify the whole thing. So my basic design guidelines now are:
- Simplicity
- Clean, clear, cool design
- No clutter
- No gimmicks
To this end, I want:
- A simple 3 or 4 colour scheme
- An easy to read background for text
- A good simple neat navbar
- Some nice but subtle shadows around some elements
- A simple background or header image
- A design that resizes nicely
More questions
Can you think of an analogy to describe HTML, CSS and the DOM? How would you describe it to your non-technical friend?
OK, this is not an original analogy but here goes...The HTML is like the structure of a building. So foundations, walls, roof, doors, beams, columns, floorboards, cladding, and suchlike could all be compared to HTML elements. Some elements (e.g. room) can contain other elements (e.g. floorboards).  They can all be changed relatively easily to give a different look and feel. The DOM is like a diagram of how the elements fit together.
What is meant by boxifying design?
This is simply the process of taking an existing graphical page design and dividing it visually into a number of boxes. These boxes may then be divided into a number of further (and smaller) boxes. These boxes may be represented in the HTML by tags such as div.
What is the box model?
In HTML everything is boxes. That is, every element in HTML renders on the page in a box of some kind. This includes shapes such as circles and the like(although the box may not be visible). So the page layout may be thought of as simply a collection of boxes.


---
layout: default
---
{{ page.title | remove: "| Vis Design Lab" }}
Faculty
{% include person.html key="meyer" %}
{% include person.html key="lex" %}
PhD Students
{% include person.html role="phdstudent" %}
Masters Students
{% include person.html role="msstudent" %}
Undergraduate Students
{% include person.html role="undergrad" %}


About BC Mine Information
The Ministry of Energy, Mines and Petroleum Resources (EMPR), Ministry of Environment and Climate Change Strategy (ENV) and Environmental Assessment Office (EAO) have collaborated to make information on the Province’s oversight of major mines in British Columbia more accessible than ever before.
This is the first time mine-related information from all three agencies has been made available online in one place, and more information will be added on an ongoing basis.
This site currently profiles 19 major mines across the province. Information on these mines will be continually added to the website, and other permitted major mines in BC will be added in the coming months.
If you want to learn more about a major mine not yet included on this website, please visit mines.empr.gov.bc.ca.
Fast Facts about the Mining Industry in British Columbia
-
$6.3B 2016 Production Value of Mining [Natural Resources Canada Preliminary Estimate]
-
$205M 2016 Industry Mineral Exploration Spending [British Columbia Geological Survey]
-
6 Number of environmental assessment applications for mining projects under review
Mining in British Columbia
The Mining Lifecycle
It can take decades to develop a deposit into a mine, which in turn can operate for decades
Learn MoreTopics of Interest
Profiling key topics of interest regarding mining activities in British Columbia
Learn MoreOur Processes & Procedures
Legislation
Learn about the key statutes and regulations that apply to mining activities in the province of British Columbia.
Learn MoreAuthorizations
Environmental assessment certificates and permits issued under the Mines Act and Environmental Management Act
Learn MoreCompliance Oversight
Several provincial agencies work together to provide integrated oversight of British Columbia’s mining sector
Learn More


odsDatasetContext
ods-widgets
A "dataset context" represents a dataset, and a set of parameters used to query its data. A context can be used by one or more directives, so that they can share information (generally the query parameters). For example, a directive that displays a time filter can be "plugged" on the same context as a table view directive, so that the user can filter the data displayed in the table.
The odsDatasetContext
creates a new child scope, and exposes its contexts into it. In other words, the contexts
will be available to any directive that is inside the odsDatasetContext
element. You can nest odsDatasetContext
directives inside each others.
A single odsDatasetContext
can declare one or more context at once. To initialize contexts, you declare
them in the context attribute. Then, you can configure them further using attributes prefixed by the context
name (CONTEXTNAME-SETTING, e.g. mycontext-domain). The available settings are:
domain
- string - (optional) Indicate the "domain" (used to construct an URL to an API root) where to find the dataset.
Domain value can be:
a simple alphanum string (e.g. mydomain): it will assume it is an Opendatasoft domain (so in this example mydomain.opendatasoft.com)
a hostname (e.g. data.mydomain.com)
an absolute path (e.g. /monitoring), it will be absolute to the hostname of the current page
a hostname and a path (e.g. data.mydomain.com/monitoring)
nothing: in that case, ODSWidgetsConfig.defaultDomain is used
dataset
- string Identifier of the dataset
apikey
string (optional) API Key to use in every API call for this context
sort
string (optional) Sort expression to apply initially (field or -field)
parameters
Object (optional) An object holding parameters to apply to the context when it is created. Any parameter from the API can be used here (such as q
, refine.FIELD
...)
refresh-delay
Number (optional) The number of milliseconds to wait before refreshing the context. If this parameter is omitted, the context does not automatically refresh. Minimum delay is 10000ms.
parametersFromContext
string (optional) The name of a context to replicate the parameters from. Any change of the parameters
in this context or the original context will be applied to both.
urlsync
Boolean Enable synchronization of the parameters to the page's parameters (query string). If you share the page with parameters in the URL, the context will
use them; and if the context parameters change, the URL parameters will change as well. If enabled, parameters
and parametersFromContext
won't have any effect.
Note that there can only be a single context with URL synchronization enabled, else the behavior will be unpredictable.
Once created, the context is exposed and accessible as a variable named after it. The context contains properties that you can access directly:
domainUrl: a full URL the the domain of the context, that can be used to create links
parameters: the parameters object of the context
dataset: the dataset object for this context
getDownloadURL(format[, dict options]): a method that returns an URL to download the data, including currently active filters (refinements, queries...). By default
the URL will allow to download a CSV export, but you can pass another format such as "geojson" or "json".
Two optional parameters : {'use_labels_for_header': '<true/false>', 'fields': '<list of comma separated field name>'}
getQueryStringURL([dict options]): a method that build the URL suffix (?key1=value1&key2=value2&...
) based on context parameters (active filters, refinement, sort, query...).
The optional dictionary parameter allow to build the URL with additional key/value parameters.
Note: Due to naming conventions in various places (HTML attributes, AngularJS...), context names have to be lowercase, can only contain alphanumerical characters, and can't begin with a number, "data", or "x".
<ods-dataset-context context="{string}"> </ods-dataset-context>as attribute
<ANY ods-dataset-context context="{string}"> ... </ANY>
| Param | Type | Details |
|---|---|---|
| context | string | A name (or list of names separated by commas) of contexts to declare. The contexts are further configured using specific attributes, as described below. |
<ods-dataset-context context="trees" trees-dataset="trees-in-paris"> <!-- Retrieved from a local API (no domain for the context)--> A dataset from {{trees.domainUrl}}. </ods-dataset-context>
<ods-dataset-context context="trees,events" trees-dataset="les-arbres-remarquables-de-paris" trees-domain="https://widgets-examples.opendatasoft.com/" clocks-dataset="evenements-publics-openagenda-extract" clocks-domain="widgets-examples"> <!-- Shows a list of the trees --> <ods-table context="trees"></ods-table> <!-- Shows a map of clocks --> <ods-map context="events"></ods-map> </ods-dataset-context>
<ods-dataset-context context="demographics" stations-dataset="us-cities-demographics" stations-domain="https://widgets-examples.opendatasoft.com/" stations-parameters="{'q': 'Santa', 'refine.state': 'California'}"> <!-- Demographics for all cities in California that have 'Santa' in their name --> <ods-table context="demographics"></ods-table> </ods-dataset-context>


@(user: securesocial.core.Identity, userId: Long, leagueId: Long) @import securesocial.core.IdentityProvider @import securesocial.core.Registry @import securesocial.core.AuthenticationMethod._ @import securesocial.core.providers.utils.RoutesHelper @import Http.Context.Implicit @main("Paramount Investment League - Join League", user.fullName, userId, leagueId) {
| # | Name | Owner Id | Initial Balance | Brokerage Fee | Join |
|---|


This is a placeholder
This is a fallback
This is a placeholder
This is a fallback
Actions
Analytics Events
| Time of Day | Autoplay | Type | Current Time | % | Played Total | Duration |


view photos tagged flickrdupfinder to review what you tagged.
visit ng-flickrdupfinder on flickr app garden - if you liked using the software I would appreciate if you marked it as a favorite!
please report bugs or leave feedback using the ? bubble in the upper left corner or vote for future features on the ng-flickrdupfinder uservoice forum!


--- layout: archive title: Zulip Chat Archive permalink: /stream/113489-new-members/topic/trivial.20ordering.html ---
Hey, quick question. I was wondering if there was a canonical way to show that i < j
for two naturals i
and j
where their value is known.
I know I can repeatedly apply nat.le_of_succ_le_succ
and then use nat.zero_le
, but that feels very cumbersome for proving something that's trivially true
Or rather the inverse of le_of_succ_le_succ
, succ_le_succ
I think?
norm_num
import tactic example : 12345 < 67890 := by norm_num
NB it only works if i is actually less than j.
:pray:
I knew there had to be a better way
When I asked that question a couple of years ago, there wasn't ;-)
Hahahaha, glad to be here at Lean 3
I had Lean 3, it was just that import tactic
imported far fewer tactics.
Ah gotcha
Also I finished Natural Number Game recently, I really like what you and Mohammed put together
Mathlib is a misnomer. It contains a whole bunch of other useful things too.
I'm sorry NNG looks so amateurish. We're both mathematicians ;-)
example : 5 < 23 := dec_trivial
The problem with that is it doesn't scale, because it does exactly what you were suggesting to do, so with 5-digit numbers things get a bit horrible.
I'm only looking to use it on small numbers
dec_trivial
is a cool tactic. It says "If this statement is decidable in the sense of logic, then decide it!"
-- We define a score to be a vector of natural numbers of length n. Each value -- score_i corresponds to the number of violations that occurred in the ith -- constraint. def score (n : ℕ) := vector ℕ n -- We define an ordering on scores such that s₁ ≤ s₂ iff they are equal up to -- some index i, wherein s₁[i] ≤ s₂[i]. def score_le {n : ℕ} (s1 : score n) (s2 : score n) : Prop := ∃ (i : ℕ) (h : i < n), nth s1 ⟨i, h⟩ ≤ nth s2 ⟨i, h⟩ ∧ ∀ (j : ℕ) (h' : j < i), nth s1 ⟨j, lt.trans h' h⟩ = nth s2 ⟨j, lt.trans h' h⟩
so long as score vectors stay small at least
And there's a proof that i<j
is decidable, and indeed you sketched the proof above. So dec_trivial
runs through that proof.
score
! Are you making a game? Lean pong would be cool.
Reducing from PCP into a model of representing phonology
Maybe that's what kids want these days.
I'll pitch it to publishers
"It's a game where you do computability theory proofs"
Get CS undergrads to play it.
norm_num
does the more sensible thing of converting everything to binary and then working with it using more sensible (but still formally verified) algorithms.
When I asked the question you asked, there was tactic.norm_num
but not tactic.interactive.norm_num
, which meant that the guts were there but you couldn't use it in tactic mode. Within about a week Mario Carneiro had got it working in tactic mode and I could then do all the inequalities I wanted. There have been countless cases like this, where someone needs something technical, mentions it on the chat, and then someone else knocks it up. The whole thing is quite an amazing project.
Yeah, I've actually been getting in trying to contribute to Lean. I'm about to start work so I'll probably hold off until I become more situated therein but don't be surprised if you find my name on some commits :slight_smile:
Also I don't know enough to ask the question right, but I'll try my best: is the norm_num
/ dec_trivial
contrast at all related to the provably correct Lean kernel(?) I've heard about?
or since norm_num
is formally verified is it still considered to be a provably correct member of that kernel
dec_trivial
is just using the stupidest algorithm. norm_num
is doing a whole lot more work -- but it is still formally verified.
You would be able to tell if it were not formally verified -- the kernel would not let the proof go through.
Gotcha, very cool!
So it's doing basic integer arithmetic but with a more optimised representation (Lean's definition of a natural is just some unwieldy linked list, so the first trick is to move to the num
class which is naturals but stored in binary)
I vaguely remember a proof in my Formal Language Theory about how an n-ary representation with n > 1
is exponentially more efficient than unary
so that makes sense
It uses something which might be called reflection to construct a theorem about nums which is provably equivalent to the theorem about nats, and then proves the theorem about nums using formally verified but fast algorithms
It uses something which might be called reflection to construct a theorem about nums which is provably equivalent to the theorem about nats, and then proves the theorem about nums using formally verified but fast algorithms
That's very cool
1,000,000 : nat is stored as succ (succ (succ (succ ...
so it's horrible. But in num it's just essentially the binary string.
import tactic #print nat #print num #print pos_num
to see how it actually does it.
Hm. Looks like lean-mode
is angry about import tactic
. Time to try it in vscode and maybe spend my evening debugging elisp instead of writing proofs
I'm about to go to bed, but to avoid a misunderstanding: norm_num
has nothing to do with the num
type and isn't proof by reflection. It works on terms of type nat
that have the structure of binary numerals. I'm happy to write more tomorrow if you're really curious (and I'm sure others could explain too).
Also I don't know enough to ask the question right, but I'll try my best: is the
norm_num
/dec_trivial
contrast at all related to the provably correct Lean kernel(?) I've heard about?
This is probably needless pedantry, but: the lean kernel is not provably correct, nor is it proven correct. It is rather the "source of truth" for all derivations done in lean, meaning that any tactics or terms that are created must pass through the kernel before being certified by it, so that as long as the kernel is correct and consistent then everything else is too. That's the "small trusted kernel" idea. (This does not mean that the kernel is bug-free, but we haven't found any soundness-critical issues in the history of lean AFAIK.)
Definitely not needless pedantry, that's quite a big difference
were it proven correct then all proofs validated by lean would necessarily be valid vs. their validity being motivated, right?
the question is: valid with respect to what?
Even if you prove the correctness of lean in some other formal prover, you are still trusting that prover as the source of truth. You can't eliminate this any more than you can do mathematics without any axioms
Fair point. Are you getting after the fact that proofs in Lean are necessarily valid with respect to the Lean kernel? And discrepancies between the kernel and--
yeah I suppose that encapsulates it better than I could :slight_smile:
And even in constructing a proof outside of a formal prover, it's a motivation towards its correctness because of space for error?
You can also do a "paper proof" of correctness/consistency, and in fact I have done so for lean (see https://github.com/digama0/lean-type-theory/releases/tag/v1.0). But that doesn't cover implementation correctness, only soundness of the underlying type theory
And it is still subject to general issues with paper proofs, namely gaps in mathematical presentation and human error
I'll take a look at the proof. And that all makes sense
The proof shows that lean is consistent relative to ZFC with omega inaccessible cardinals (which are needed for the universe hierarchy)
I don't have a great mathematical maturity--I'm familiar with ZFC, but not with omega inaccessible carindals
What are they?
That's omega many (i.e. indexed by natural numbers) inaccessible cardinals, in an increasing sequence
Gotcha!
an inaccessible cardinal is basically a set which is large enough to model ZFC
so you have a whole sequence of nested models of ZFC
It's a pretty weak condition as far as large cardinal assumptions go
But ZFC itself doesn't cut it because lean can prove ZFC is consistent
Ah interesting, I wasn't aware that you could prove ZFC's consistency in Lean. That's very cool
See the file set_theory.zfc
in mathlib, which explicitly constructs a model
found it, will review later
{% endraw %}Last updated: Apr 24 2020 at 19:02 UTC


If, after reading the introduction, you're not quite sure about the purpose of the project, have a look at the diagram below:
It shows a basic use case of the project: the client has a graph of objects (whether it was created locally or obtained from the server is not important for now) which it wants to change and save on the server. In this simple case we assume that it's not a real graph but a single object.
First it calls a method on this object: e.g. someObject.setName("foo"). As 'someObject' is an instance of a 'smart' VO, it detects the change of state and updates its version information to 'modified'.
Then, when the user wants to save the data, it tells a component called mediator to perform an update by calling updateGraph(someObject) (step 2). This component will then verify that the object has been changed (step 3), and do the actual update (step 4).
The analysis of modifications can prove useful in a client/server scenario, where the state of the client must be synchronized with the server. By only sending modified objects the network traffic can be reduced drastically.
| back | index | next |


mkbook is my simpler alternative to mdbook which is a great tool, however I really dislike some of the decisions they took—such as relying on javascript for highlighting and navigation and including a lot of bells and whistles such as javascript-based search.
This tool aims to work somewhat similarly to mdbook, but is generally intended to be a more minimal alternative that is customized more towards my needs and desires than anything else.
If you’re not familiar with mdbook, mkbook is a tool to convert a collection of Markdown files into a static website / book which can be published online. It was created to help me write documentation with minimum fuss while presenting it in an easy-to-consume manner.


The goal of this website was to educate users on the how the internet has evolved. The internet has come a long was from just a thought, and through this website, you will be able to see how much has come from just this single thought.
This website was made to educate all ages on the topic of the internet. It is very important that we all know specifically where most of our time is spent. It is very surprising once anyone finds out how their favorite apps came from just a thought. Those thoughts were then turned into reality when someone had an idea to make the internet and all it has to offer.
The topics of the website include a beginning page where we go back all the way to the start of the internet which was known as the ARPANET. Then we get into Internet Service Providers and programs like Windows. We finally come all the way to the creation of some of out favorite sites like YouTube and Twitter.


Filters in Nimbits allows you to filter out noise in incoming data. This is very useful if you are recording a reading that doesn't change much, or fluctuates between small changes but you are only interested in significant changes. For example, a sensor that always reads the number 42.0 over and over again every second. Perhaps sometimes the value changes to 42.1 or 41.9 but that's just considered noise. You only want to actually record changes in readings of 1 or more. You would configure your data point to have a Fixed Hysteresis filter of 1.0.
When a new value is recorded to a Data Point, one of the first things that are checked is the filter setting. Filters tell Nimbits to only record values that are outside of the range of the filter setting, or if the incoming RecordedValue is significantly different than the previously recorded value, so it is worth putting in the data store. default setting for a new DataPoint PointFilter is .1


I am Jerry Daniels Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever It has survived not only five centuries, but also the leap into electronic but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing
6834 Hollywood Blvd - Los Angeles CA
<EMAIL_ADDRESS>+20 010 2517 8918


Fully customized app development without use of any libraries other than Angular and jQuery.
Gulp developemt with multiple environments with all custom JS, SCSS, glyphs icons.
Multiple theme versions
Mobile first design
Single page AngularJS MV* aproach
2 build environments (development and production)
SCSS and JS, concatenate and minify
Github for development method and process
Select your preferred method of contact.


This is the entry point of the SDK. It defines the ClusterRunner class. Author: Lu Pan Source: client.js, line 1
A network object which abstracts away how the request is being made in node or browers. Author: Lu Pan Source: network.js, line 1


{{ d.preview }}
{{ _("No matching records. Search something new") }} {% else %}
{{ _("Type something in the search box to search") }} {% endif %}


Toggle navigation
TV
Movies
Calendar
Discover
Apps
VIP
Batman!
Holy cripes! It's Batman!
Learn more
Batman!
Bat Signal
Click here!


AtomicalJS Playground
Content inside a div.
Click me!
Click me too!
FadeIn
FadeIn 2
FadeOut
Also me!
Off
Last Button


View console.
This test compares parse speed of multiple input types (Blob, ArrayBuffer, URL, Base64, img element, etc...)
Parser options are set to absolute minimum needed to extract GPS coords as fast as possible.


1. AI Doucmentation¶
This detailed reference lists all the classes and functions contained in the package. If you are just looking to get started, read the /tutorial/index first.
The Lattice
describes the unit cell of a crystal, while the Model
is used to build up a larger system by translating the unit cell to fill a certain shape or symmetry. The model builds the Hamiltonian matrix by applying fields and other modifier parameters.
1.1. Molecule System¶
1.2. Model System¶
Lattice for Model Hamiltonian |
|
1.3. Hartree Fock¶
1.4. Post Hartree Fock¶
|
|
1.5. Property¶
|
|