I know I can make tcl functions with optional input parameters. So if you don't enter a value for those parameters they can take on the default value that you give them. My question is when I call a function with optional parameters is it possible to skip the input of some and enter others? Like if there are 2x optional parameters how would I enter a value for the second parameter rather than the first?
I haven't really tried anything specifically because I'm not sure how to get around this problem.
proc area { height width {normalization 1.0} {scaling 1.0} {
....
}
[area 3 4 3.5]
Is there a way I could call area without changing the default value for normalization, while entering a value for scaling?
If I wanted a scaling value of 3.5 I can't really enter it in without also entering a value for normalization?
Yes, that's correct; if you want a scaling value of 3.5, you cannot enter it without also entering a value for normalization with the way the proc was written.
You can do something a bit more towards what you want to do with some tweaking (there's a whole wiki article discussing about ways to do this). A quick example with an array:
proc area {height width args} {
# Put the remaining parameters in an array, you might want to do validation checks before that
array set options $args
# If certain parameters are not provided, give default values
if {"-normalization" ni [array names options]} {
set options(-normalization) 1.0
}
if {"-scaling" ni [array names options]} {
set options(-scaling) 1.0
}
puts "Normalization: $options(-normalization)"
puts "Scaling: $options(-scaling)"
}
area 1 2 -normalization 3.5
# => Normalization: 3.5
# => Scaling: 1.0
area 1 2 -scaling 3.5
# => Normalization: 1.0
# => Scaling: 3.5
area 1 2
# => Normalization: 1.0
# => Scaling: 1.0
The pattern I use is this:
proc area {height width args} {
# The default values
set defaults {-normalization 1.0 -scaling 1.0}
# Merge with the actual arguments provided
set params [dict merge $defaults $args]
# Just extract the variables I care about using [dict update] with an empty body
dict update params -normalization norm -scaling scale {}
# Demonstrate what's been extracted
puts "Parameters: $height $width $norm $scale"
}
area 2 3 -scaling 17.3
This isn't perfect since it doesn't warn/error about unexpected arguments, provide a discovery mechanism, or handle argument name abbreviation, but it's simple and cheap and fairly fast. There have been proposals for changing that (I'm aware of two TIPs: 457, 479) but none have really gained traction so far; it's an area that is a tricky compromise between flexibility and performance.
(If you use the variable name as the actual parameter name and don't care at all about wrong arguments, you can just use dict with to do the extraction.)
A shorter version (using the same basic idea) might be:
proc area {height width args} {
array set {} [dict merge {-normalization 1.0 -scaling 1.0} $args]
puts "Parameters: $height $width $(-normalization) $(-scale)"
}
This uses the variable with the empty name as an array. Yes, that's legal (and relatively convenient) but I've never really warmed to it myself.
There have been proposals for changing that (I'm aware of two TIPs:
457, 479) but none have really gained traction so far.
If you are willing to use an established Tcl extension (https://next-scripting.org/), you can benefit from optional named parameters when implementing a proc:
package req nsf
nsf::proc area {height width {-normalization 1.0} {-scaling 1.0}} {
puts "arguments: $height $width $normalization $scaling"
}
area 1 2 -normalization 3.5
# arguments: 1 2 3.5 1.0
area 1 2 -scaling 3.5
# arguments: 1 2 1.0 3.5
area 1 2
# arguments: 1 2 1.0 1.0
Related
I have a list which looks like
list = {ab bc 8 ab d1 10 xy uv bc ab xy 10 d1}
I would like to know how often each element of the list occurs inside it, that is, I need a result like this:
ab 3
bc 2
8 1
d1 2
....
I prefer a single line argument (if such exists) instead of a proc. I need to work with both: list elements and their frequency in the list.
Any advice is welcome.
Thank you!
Assuming that counter is the name of the dictionary where you want to collect this information (and is either currently unset or set to the empty string):
foreach item $list {dict incr counter $item}
You can then print that out in approximately the form you gave with:
dict for {item count} $counter {puts [format "%6s %-3d" $item $count]}
Note that this second line is about displaying the data, not actually finding it out.
I am trying to capture some data in TCL. I have below data :
{0.0 0.0} {0.741 0.48}
My required out put is 3rd column of this data.
0.741
how can i achieve it?
set oaDesign [ed]
set rprb [db::getShapes -of $oaDesign -lpp {INST_B drawing}]
set r [de::getBBox $rprb]
puts $r
{0.0 0.0} {0.741 0.48}
I just need 3rd column, which is 0.741
You would use lindex and lset, respectively, to access the nested list's elements at a known position:
% lindex $r 1 0
0.741
To write back into that list of lists, at a given position:
% lset r 1 0 0.0
{0.0 0.0} {0.0 0.48}
Did you search SO for previous answers, before raising your question?
This code snippet works just fine under python 3.6.4 but is triggering a portability issue when present in .pyx files. I could use some help figuring out how to best format python 3.5.1+ bytes in Cython.
EDIT: Changing this in light of DavidW's comment.
Following works in python 3.6.4 under ipython
def py_foo():
bytes_1 = b'bytes 1'
bytes_2 = b'bytes 2'
return b'%(bytes_1)b %(bytes_2)b' % {
b'bytes_1': bytes_1,
b'bytes_2': bytes_2}
As hoped this results in:
print(py_foo())
b'bytes 1 bytes 2'
Using cython with the only changes to the code being the name of the function, a return type declared, and declaring the two variables.
%load_ext Cython
# Cython==0.28
followed by:
%%cython
cpdef bytes cy_foo():
cdef:
bytes bytes_1, bytes_2
bytes_1 = b'bytes 1'
bytes_2 = b'bytes 2'
return b'%(bytes_1)b %(bytes_2)b' % {
b'bytes_1': bytes_1,
b'bytes_2': bytes_2}
Results in:
Error compiling Cython file:
....
return b'%(bytes_1)b %(bytes_2)b' % {
^
..._cython_magic_b0aa5be86bdfdf75b98df1af1a2394af.pyx:7:38: Cannot convert 'basestring' object to bytes implicitly. This is not portable.
-djv
I'm not sure if this is a useful answer or just a more detailed diagnosis, but: the issue is with the return type. If you do:
cpdef cy_foo1(): # no return type specified
# everything else exactly the same
then it's happy. If you do
cpdef bytes cy_foo2():
# everything else the same
return bytes(b'%(bytes_1)b %(bytes_2)b' % {
b'bytes_1': bytes_1,
b'bytes_2': bytes_2})
then it's happy. If you do
def mystery_function_that_returns_not_bytes():
return 1
cpdef bytes cy_foo3():
return mystery_function_that_returns_not_bytes()
then it compiles happily but gives a runtime exception (as you would expect)
The issue seems to be that it knows bytes % something returns a basestring but it isn't confident that it returns bytes and isn't prepared to leave it until runtime to try (unlike the cases where it's totally sure, or completely unsure, when it will leave it until runtime).
The above examples show a couple of ways of working round it. Personally, I'd just remove the return type - you don't get a lot of benefit from typing Python objects such as bytes anyway. You should probably also report this as a bug to https://github.com/cython/cython/issues
I am working on generating an HTML page using a CGI script in Perl.
I need filter some sequences in order to check whether they contain a specific pattern; if they contain it I need to print those sequences on my page with 50 bases per line, and highlight the pattern in the sequences. My sequences are in an hash called %hash; the keys are the names, the values are the actual sequences.
my %hash2;
foreach my $key (keys %hash) {
if ($hash{$key} =~ s!(aaagg)!<b>$1</b>!) {
$hash2{$key} = $hash{$key}
}
}
foreach my $key (keys %hash2) {
print "<p> <b> $key </b> </p>";
print "<p>$_</p>\n" for unpack '(A50)*', $hash2{$key};
}
This method "does" the job however if I highlight the pattern "aaagg" using this method I am messing up the unpacking of the line (for unpack '(A50)*'); because now the sequences contains the extra characters of the bold tags which are included in the unpacking count. This beside making the lines of different length it is also a big problem if the tag falls between 2 lines due to unpacking 50 characters, it basically remains open and everything after that is bold.
The script below uses a single randomly generated DNA sequence of length 243 (generated using http://www.bioinformatics.org/sms2/random_dna.html) and a variable length pattern.
It works by first recording the positions which need to be highlighted instead of changing the sequence string. The highlighting is inserted after the sequence is split into chunks of 50 bases.
The highlighting is done in reverse order to minimize bookkeeping busy work.
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
use YAML::XS;
my $PRETTY_WIDTH = 50;
# I am using bold-italic so the highlighting
# is visible on Stackoverflow, but in real
# life, this would be something like:
# my #PRETTY_MARKUP = ('<span class="highlighted-match">', '</span>');
my #PRETTY_MARKUP = ('<b><i>', '</i></b>');
use constant { BAŞ => 0, SON => 1, ROW => 0, COL => 1 };
my $sequence = q{ccggtgagacatccagttagttcactgagccgacttgcatcagtcatgcttttccccgtaatgagggccccatattcaggccgtcgtccggaattgtcttggatccggaatgcagcttttctcaccgcttgatgaacattcactgaatatctgacgccgcgaaaacagggtcactagcctgtttccggtcgcccgagaccggcgagtttgtggtatcgcgagcgcccccgggcggtagggtct};
my $wanted = 'c..?gg';
my #pos;
while ($sequence =~ /($wanted)/g) {
push #pos, [ pos($sequence) - length($1), pos($sequence) ];
}
print Dump \#pos;
my #output = unpack "(A$PRETTY_WIDTH)*", $sequence;
print Dump \#output;
while (my $pos = pop #pos) {
my #rc = map pos_to_rc($_, $PRETTY_WIDTH), #$pos;
substr($output[ $rc[$_][ROW] ], $rc[$_][COL], 0, $PRETTY_MARKUP[$_]) for SON, BAŞ;
}
print Dump \#output;
sub pos_to_rc {
my $r = int( $_[0] / $_[1] );
my $c = $_[0] - $r * $_[1];
[ $r, $c ];
}
Output:
C:\...\Temp> perl s.pl
---
- - 0
- 4
- - 76
- 80
- - 87
- 91
- - 97
- 102
- - 104
- 108
- - 165
- 170
- - 184
- 188
- - 198
- 202
- - 226
- 231
---
- ccggtgagacatccagttagttcactgagccgacttgcatcagtcatgct
- tttccccgtaatgagggccccatattcaggccgtcgtccggaattgtctt
- ggatccggaatgcagcttttctcaccgcttgatgaacattcactgaatat
- ctgacgccgcgaaaacagggtcactagcctgtttccggtcgcccgagacc
- ggcgagtttgtggtatcgcgagcgcccccgggcggtagggtct
---
- ccggtgagacatccagttagttcactgagccgacttgcatcagtcatgct
- tttccccgtaatgagggccccatattcaggccgtcgtccggaattgtctt
- ggatccggaatgcagcttttctcaccgcttgatgaacattcactgaatat
- ctgacgccgcgaaaacagggtcactagcctgtttccggtcgcccgagacc
- ggcgagtttgtggtatcgcgagcgcccccgggcggtagggtct
Especially since this turns out to have been a homework assignment, it is now up to you to take this and apply it to all sequences in your hash table.
Is it possible for MySQL database to generate a 5 or 6 digit code comprised of only numbers and letters when I insert a record? If so how?
Just like goo.gl, bit.ly and jsfiddle do it. For exaple:
http://bit.ly/3PKQcJ
http://jsfiddle.net/XzKvP
cZ6ahF, 3t5mM, xGNPN, xswUdS...
So UUID_SHORT() will not work because it returns a value like 23043966240817183
Requirements:
Must be unique (non-repeating)
Can be but not required to be based off of primary key integer value
Must scale (grow by one character when all possible combinations have been used)
Must look random. (item 1234 cannot be BCDE while item 1235 be BCDF)
Must be generated on insert.
Would greatly appreciate code examples.
Try this:
SELECT LEFT(UUID(), 6);
I recommend using Redis for this task, actually. It has all the features that make this task suitable for its use. Foremost, it is very good at searching a big list for a value.
We will create two lists, buffered_ids, and used_ids. A cronjob will run every 5 minutes (or whatever interval you like), which will check the length of buffered_ids and keep it above, say, 5000 in length. When you need to use an id, pop it from buffered_ids and add it to used_ids.
Redis has sets, which are unique items in a collection. Think of it as a hash where the keys are unique and all the values are "true".
Your cronjob, in bash:
log(){ local x=$1 n=2 l=-1;if [ "$2" != "" ];then n=$x;x=$2;fi;while((x));do let l+=1 x/=n;done;echo $l; }
scale=`redis-cli SCARD used_ids`
scale=`log 16 $scale`
scale=$[ scale + 6]
while [ `redis-cli SCARD buffered_ids` -lt 5000 ]; do
uuid=`cat /dev/urandom | tr -cd "[:alnum:]" | head -c ${1:-$scale}`
if [ `redis-cli SISMEMBER used_ids $uuid` == 1]; then
continue
fi
redis-cli SADD buffered_ids $uuid
done
To grab the next uid for use in your application (in pseudocode because you did not specify a language)
$uid = redis('SPOP buffered_ids');
redis('SADD used_ids ' . $uid);
edit actually there's a race condition there. To safely pop a value, add it to used_ids first, then remove it from buffered_ids.
$uid = redis('SRANDMEMBER buffered_ids');
redis('SADD used_ids ' . $uid);
redis('SREM buffered_ids ' . $uid);