Pretty print in Hy? - hy

Is there something like pprint or clojure.pprint/pprint available in Hy? More specific, is there something that would convert something like this:
{:a {:a 0 :b 1 :c 2 :d 3 :e 4} :b {:a 0 :b 1 :c 2 :d 3 :e 4} :c {:a 0 :b 1 :c 2 :d 3 :e 4} :d {:a 0 :b 1 :c 2 :d 3 :e 4} :e {:a 0 :b 1 :c 2 :d 3 :e 4}}
In this (this is an example, doesn't need to be exactly like below):
{:e {:e 4 :d 3 :c 2 :b 1 :a 0}
:d {:e 4 :d 3 :c 2 :b 1 :a 0}
:c {:e 4 :d 3 :c 2 :b 1 :a 0}
:b {:e 4 :d 3 :c 2 :b 1 :a 0}
:a {:e 4 :d 3 :c 2 :b 1 :a 0}}
I already tried hy-repr and hydiomatic.utils/hypprint, however hy-repr didn't seem to pretty print long maps and hydiomatic does not work in recent versions of Hy.

No. Feel free to file an issue requesting it. However, our Emacs package, hy-mode, does have some auto-indent features (partly borrowed from Emacs's generic Lisp-editing code), and probably the Vim plugin does too, but that's been less actively maintained (to nobody's surprise, Lispers tend to prefer Emacs).

Related

how to use something like if and else in batch

#echo off
mode 1000
goto block1
:block1
echo color
goto block2
:block2
pause
set /a num=%random% %%5
goto 0
:0
if num == 0 goto a
goto 1
:1
if num == 1 goto b
goto 2
:2
if num == 2 goto c
goto 3
:3
if num == 3 goto d
goto 4
:4
if num == 4 goto e
goto 5
:5
if num == 5 goto f
goto 0
:a
color 0a
goto block2
:b
color 0b
goto block2
:c
color 0c
goto block2
:d
color 0d
goto block2
:e
color 0e
goto block2
:f
color 0f
goto block2
i want to make a color sign witch changes colors and i would like use simething like this . but i cant use else in batch and it would need something like that
From batch view point nearly all the gotos are useless and only
result in spaghetti code.
You are aware that a color stement will affect the whole screen?
%random% modulus 5 can only return 0..4
Your code shortened :
#echo off
mode 1000
echo color
:block2
pause
set /a num=%random% %%5
if %num% == 0 color 0a
if %num% == 1 color 0b
if %num% == 2 color 0c
if %num% == 3 color 0d
if %num% == 4 color 0e
goto block2

Filter duplicates in a batch arguments array

I'm writing a batch, where a user must input a list of devices to activate as batch arguments. The list may contain device numbers and/or names in random order with possible duplicates and invalids (i.e. non-existing or not Ready devices). The batch :default section stores an array dev_#=name of all currently Ready devices in random order. The initial task is to filter the user input to exclude duplicates and invalids, and present a list of sorted ready device numbers to activate. Then the devices from that list are activated. What efficient short code would do the filtering task?
#echo off
setlocal EnableDelayedExpansion
:default
set "dev_1=AB" & set "dev_2=BA" & set "dev_3=AC" & set "dev_16=CA" & set "dev_19=BC" & set "dev_6=CB" & set "dev_7=ZA"
set "dev_8=AZ" & set "dev_29=UA" & set "dev_10=YZ" & set "dev_18=YW" & set "dev_12=AK" & set "dev_13=AJ" & set "dev_14=HT"
rem batch arguments entered by user
rem 1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA
rem Desired sorted filtered output
rem 1 2 3 6 7 10 12
One liner with native batch commands - no way!
But it doesn't take a lot of code, especially if you are creative with designing some data structures. Note that the only code that counts is the :test routine. The rest is intitialization and test cases.
#echo off
setlocal
:: Clear devices
for /f "delims==" %%A in ('set dev. 2^>nul') do set "%%A="
:: Define devices
for %%A in (
" 1=AB" " 2=BA" " 3=AC" "16=CA" "19=BC" " 6=CB" " 7=ZA"
" 8=AZ" "29=UA" "10=YZ" "18=YW" "12=AK" "13=AJ" "14=HI"
) do for /f "tokens=1,2 delims==" %%a in (%%A) do for %%N in (%%a) do (
set "dev.%%N= %%a"
set "dev.%%b= %%a"
)
call :test 1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA
call :test sadf asdfa
call :test aj 6 13 CB
exit /b
:test
setlocal EnableDelayedExpansion
:: Clear selected
for /f "delims==" %%A in ('set selected. 2^>nul') do set "%%A="
:loadArgs Define a variable for each unique device specified in args
if "%~1" neq "" (
if defined dev.%~1 set "selected.!dev.%~1!=1"
shift /1
goto :loadArgs
)
:: Write out the unique values in sorted order
set "dev= "
for /f "tokens=2 delims== " %%A in ('set selected. 2^>nul') do set "dev=!dev!%%A "
echo selected devices = %dev:~1%
exit /b
--OUTPUT--
selected devices = 1 2 3 6 7 10 12
selected devices =
selected devices = 6 13
If you are confident that users will never include *, ?, or ) within the arguments, then a FOR loop can replace the GOTO loop. The :test routine simplifies to the following:
:test
setlocal EnableDelayedExpansion
:: Clear selected
for /f "delims==" %%A in ('set selected. 2^>nul') do set "%%A="
:: Define a variable for each unique device specified in args
for %%A in (%*) do if defined dev.%%~A set "selected.!dev.%%~A!=1"
:: Write out the unique values in sorted order
set "dev= "
for /f "tokens=2 delims== " %%A in ('set selected. 2^>nul') do set "dev=!dev!%%A "
echo selected devices = %dev:~1%
exit /b
Now if you are willing to step outside the bounds of pure native batch, then a one liner is certainly doable. I would use my JSORT.BAT and JREPL.BAT utilities. JSORT is able to sort numbers, so leading spaces are no longer needed in the initialization values.
Now the :test routine is truly a one liner:
#echo off
setlocal
:: Clear devices
for /f "delims==" %%A in ('set dev. 2^>nul') do set "%%A="
:: Define devices
for %%A in (
"1=AB" "2=BA" "3=AC" "16=CA" "19=BC" "6=CB" "7=ZA"
"8=AZ" "29=UA" "10=YZ" "18=YW" "12=AK" "13=AJ" "14=HI"
) do for /f "tokens=1,2 delims== " %%a in (%%A) do (
set "dev.%%a=%%a"
set "dev.%%b=%%a"
)
call :test 1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA
call :test sadf asdfa
call :test aj 6 13 CB
exit /b
:test
(for %%A in (. %*) do #call echo(%%dev.%%A%%) | jsort /n /u | jrepl "(\s|%%.*?%%)+" " " /m | jrepl "^ " ""
exit /b
or
:test
echo(%*|jrepl "(^|\s*)(\S+)" "env('dev.'+$2)" /jmatch | jsort /n /u | jrepl "\s+" " " /m | jrepl "^ " ""
exit /b
If you are open to alternatives, here is an example in VBScript (save in a file with .vbs extension instead of .bat ):
input = InputBox("", , "1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA")
values = Split(input)
' Adds the values to a sorted list that matches the case
Set list = CreateObject( "System.Collections.Sortedlist" )
For Each value in values
Select Case value
Case "1" , "AB" : list(1 ) = 0
Case "2" , "BA" : list(2 ) = 0
Case "3" , "AC" : list(3 ) = 0
Case "6" , "CB" : list(6 ) = 0
Case "7" , "ZA" : list(7 ) = 0
Case "8" , "AZ" : list(8 ) = 0
Case "10", "YZ" : list(10) = 0
Case "12", "AK" : list(12) = 0
Case "13", "AJ" : list(13) = 0
Case "14", "HT" : list(14) = 0
Case "16", "CA" : list(16) = 0
Case "18", "YW" : list(18) = 0
Case "19", "BC" : list(19) = 0
Case "29", "UA" : list(29) = 0
End Select
Next
' To show the items in the list
For i = 0 To list.Count - 1
output = output & list.GetKey(i) & " "
Next
MsgBox output
Another alternative is PowerShell (extension .ps1):
$s = "1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA"
$a = -split $s
$a = $a -replace "AB", 1
$a = $a -replace "BA", 2
$a = $a -replace "AC", 3
$a = $a -replace "CB", 6
$a = $a -replace "ZA", 7
$a = $a -replace "AZ", 8
$a = $a -replace "YZ", 10
$a = $a -replace "AK", 12
$a = $a -replace "AJ", 13
$a = $a -replace "HT", 14
$a = $a -replace "CA", 16
$a = $a -replace "YW", 18
$a = $a -replace "BC", 19
$a = $a -replace "UA", 29
$a = $a | ? { -split "1 2 3 6 7 8 10 12 13 14 16 18 19 29" -contains $_ }
$l = $a | % { iex $_ }
$l = $l | sort-object -Unique
$l -join " "
But running a PowerShell script is a bit challenging, so instead you can run it from a .bat file like this:
powershell -noprofile -command "&{"^
"$s = '1 3 6 AB BA YZ 12 17 21 YK AU AK BA BU ZA' ;"^
"$a = -split $s ;"^
"$a = $a -replace 'AB', 1 ;"^
"$a = $a -replace 'BA', 2 ;"^
"$a = $a -replace 'AC', 3 ;"^
"$a = $a -replace 'CB', 6 ;"^
"$a = $a -replace 'ZA', 7 ;"^
"$a = $a -replace 'AZ', 8 ;"^
"$a = $a -replace 'YZ', 10 ;"^
"$a = $a -replace 'AK', 12 ;"^
"$a = $a -replace 'AJ', 13 ;"^
"$a = $a -replace 'HT', 14 ;"^
"$a = $a -replace 'CA', 16 ;"^
"$a = $a -replace 'YW', 18 ;"^
"$a = $a -replace 'BC', 19 ;"^
"$a = $a -replace 'UA', 29 ;"^
"$a = $a | ? { -split '1 2 3 6 7 8 10 12 13 14 16 18 19 29' -contains $_ } ;"^
"$l = $a | %% { iex $_ } ;"^
"$l = $l | sort-object -Unique ;"^
"$l -join ' ' ;"^
"}"
pause
It's an extended comment to show an application example for readers of native Cmd sorting used in Dave's above answer. It requires padding numbered vars with zeros.
#echo off
setlocal EnableDelayedExpansion
set "devs= 1 10 12 2 3 4 6 7 8 9"
for %%k in (!devs!) do (set /a "devl=100+%%k" & set "devl=!devl:~-2!"
set "dev.!devl!=!devl!")
for /f "tokens=2 delims==" %%l in ('set dev.') do set "devn=!devn! %%l"
echo !devn!
exit /b
:: output
:: 01 02 03 04 06 07 08 09 10 12

Convert a clojure array-map to array

If I have an array map like this:
{"red" "blue"}
How can I turn this into an array like this:
["red" "blue"]
Maps hold an unordered set of MapEntry objects, which act like vectors, so just calling first on the map will convert it to a sequence, then grab the first map entry:
(first {"red" "blue"})
; ["red" "blue"]
(vec (mapcat seq {"red" "blue"}))
; ["red" "blue"]
user> (vec (apply concat {:a 0 :b 1 :c 2 :d 3}))
[:c 2 :b 1 :d 3 :a 0]
This is similar to Thumbnail's solution, but calling seq is redundant.
Also assumed you mean vector and not array. If having the output just be linear suffices then the call to vec can be eliminated as well.
The problem with the flatten option is if there is internal structure of any sort in the map:
user> (flatten (seq {:a 0 :b 1 :c [2 3]}))
(:c 2 3 :b 1 :a 0)
user> (apply concat {:a 0 :b 1 :c [2 3]})
(:c [2 3] :b 1 :a 0)
If you want to handle empty maps as empty vectors and maps with multiple pairs as a vector of [key val key val...] then you can use reduce into [] or reduce-kv conj [].
so.core=> (reduce into [] {"red" "blue"})
["red" "blue"]
so.core=> (reduce into [] {:a 0 :b 1 :c 2 :d 3})
[:c 2 :b 1 :d 3 :a 0]
so.core=> (reduce into [] {})
[]
One and a very quick way:
(flatten (vec {"red" "blue"}))
=> ("red" "blue")
If you really want an array:
(into-array (flatten (vec {"red" "blue"})))
=> #<String[] [Ljava.lang.String;#4dc2753>
Keep in mind that in Clojure, ["red" "blue"] is a vector, not an array. And { } means map. Clojure first creates an array map but later, it promotes it to hash map when it is necessary.

Batch - How do I get it to display from all letters?

I have a simple (I hope it doesn't become complicated) batch file in which you enter in a series of letters, (possibly seperated by spaces) and it 'decrypts them' similar to those old 'decoder wheels', in this case where A=1, B=2, and so forth
This is what I have so far, but I wish to make it so it can find what you put in all together, rather than having to enter in each letter one at a time. Thanks
echo off
cls
:1
echo Enter in letters to decrypt
set /p let=
if %let%==A echo 1
if %let%==B echo 2
if %let%==C echo 3
if %let%==D echo 4
if %let%==E echo 5
if %let%==F echo 6
if %let%==G echo 7
if %let%==H echo 8
if %let%==I echo 9
if %let%==J echo 10
if %let%==K echo 11
if %let%==L echo 12
if %let%==M echo 13
if %let%==N echo 14
if %let%==O echo 15
if %let%==P echo 16
if %let%==Q echo 17
if %let%==R echo 18
if %let%==S echo 19
if %let%==T echo 20
if %let%==U echo 21
if %let%==V echo 22
if %let%==W echo 23
if %let%==X echo 24
if %let%==Y echo 25
if %let%==Z echo 26
CHOICE /C ABCDEFGHIJKLMNOPQRSTUVWXYZ /N
echo %errorlevel%

About the array in bash shell script

Just a simple question.
I have an array:
array=("1 2 3" "4 5 6")
If I do:
echo ${array[0]}
echo ${array[1]}
1 2 3 or 4 5 6 will be shown.
However, if I do:
for iter in ${array[#]}
do
echo $iter
done
The shown value is not as I expected.... Can anyone give me the right way to use it?
Quotation is what you need:
for iter in "${array[#]}"; do
echo "$iter"
done

Resources